* gcc.dg/vect/slp-perm-1.c (main): Make sure loops aren't vectorized.
[official-gcc.git] / gcc / genautomata.c
blob88d358cb86f4f3c45740ecbb673c319049ea5640
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
12 later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* References:
25 1. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
27 summit, 2003.
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
40 recognizers.
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
52 automaton state.
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
60 really need this.
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
70 VLIW insn packing.
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
79 further processing.
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
83 It can be divided on:
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
106 other gcc code. */
108 #include "bconfig.h"
109 #include "system.h"
110 #include "coretypes.h"
111 #include "tm.h"
112 #include "rtl.h"
113 #include "obstack.h"
114 #include "errors.h"
115 #include "gensupport.h"
117 #include <math.h>
118 #include "hashtab.h"
119 #include "vec.h"
121 #ifndef CHAR_BIT
122 #define CHAR_BIT 8
123 #endif
125 /* Positions in machine description file. Now they are not used. But
126 they could be used in the future for better diagnostic messages. */
127 typedef int pos_t;
129 /* The following is element of vector of current (and planned in the
130 future) functional unit reservations. */
131 typedef unsigned HOST_WIDE_INT set_el_t;
133 /* Reservations of function units are represented by value of the following
134 type. */
135 typedef set_el_t *reserv_sets_t;
136 typedef const set_el_t *const_reserv_sets_t;
138 /* The following structure describes a ticker. */
139 struct ticker
141 /* The following member value is time of the ticker creation with
142 taking into account time when the ticker is off. Active time of
143 the ticker is current time minus the value. */
144 int modified_creation_time;
145 /* The following member value is time (incremented by one) when the
146 ticker was off. Zero value means that now the ticker is on. */
147 int incremented_off_time;
150 /* The ticker is represented by the following type. */
151 typedef struct ticker ticker_t;
153 /* The following type describes elements of output vectors. */
154 typedef HOST_WIDE_INT vect_el_t;
156 /* Forward declaration of structures of internal representation of
157 pipeline description based on NDFA. */
159 struct unit_decl;
160 struct bypass_decl;
161 struct result_decl;
162 struct automaton_decl;
163 struct unit_pattern_rel_decl;
164 struct reserv_decl;
165 struct insn_reserv_decl;
166 struct decl;
167 struct unit_regexp;
168 struct result_regexp;
169 struct reserv_regexp;
170 struct nothing_regexp;
171 struct sequence_regexp;
172 struct repeat_regexp;
173 struct allof_regexp;
174 struct oneof_regexp;
175 struct regexp;
176 struct description;
177 struct unit_set_el;
178 struct pattern_set_el;
179 struct pattern_reserv;
180 struct state;
181 struct alt_state;
182 struct arc;
183 struct ainsn;
184 struct automaton;
185 struct state_ainsn_table;
187 /* The following typedefs are for brevity. */
188 typedef struct unit_decl *unit_decl_t;
189 typedef const struct unit_decl *const_unit_decl_t;
190 typedef struct decl *decl_t;
191 typedef const struct decl *const_decl_t;
192 typedef struct regexp *regexp_t;
193 typedef struct unit_set_el *unit_set_el_t;
194 typedef struct pattern_set_el *pattern_set_el_t;
195 typedef struct pattern_reserv *pattern_reserv_t;
196 typedef struct alt_state *alt_state_t;
197 typedef struct state *state_t;
198 typedef const struct state *const_state_t;
199 typedef struct arc *arc_t;
200 typedef struct ainsn *ainsn_t;
201 typedef struct automaton *automaton_t;
202 typedef struct automata_list_el *automata_list_el_t;
203 typedef const struct automata_list_el *const_automata_list_el_t;
204 typedef struct state_ainsn_table *state_ainsn_table_t;
206 /* Undefined position. */
207 static pos_t no_pos = 0;
209 /* All IR is stored in the following obstack. */
210 static struct obstack irp;
213 /* Declare vector types for various data structures: */
215 DEF_VEC_P(alt_state_t);
216 DEF_VEC_ALLOC_P(alt_state_t, heap);
217 DEF_VEC_P(ainsn_t);
218 DEF_VEC_ALLOC_P(ainsn_t, heap);
219 DEF_VEC_P(state_t);
220 DEF_VEC_ALLOC_P(state_t, heap);
221 DEF_VEC_P(decl_t);
222 DEF_VEC_ALLOC_P(decl_t, heap);
223 DEF_VEC_P(reserv_sets_t);
224 DEF_VEC_ALLOC_P(reserv_sets_t, heap);
226 DEF_VEC_I(vect_el_t);
227 DEF_VEC_ALLOC_I(vect_el_t, heap);
228 typedef VEC(vect_el_t, heap) *vla_hwint_t;
230 /* Forward declarations of functions used before their definitions, only. */
231 static regexp_t gen_regexp_sequence (const char *);
232 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
233 reserv_sets_t);
234 static reserv_sets_t get_excl_set (reserv_sets_t);
235 static int check_presence_pattern_sets (reserv_sets_t,
236 reserv_sets_t, int);
237 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
238 int);
239 static arc_t first_out_arc (const_state_t);
240 static arc_t next_out_arc (arc_t);
244 /* Options with the following names can be set up in automata_option
245 construction. Because the strings occur more one time we use the
246 macros. */
248 #define NO_MINIMIZATION_OPTION "-no-minimization"
249 #define TIME_OPTION "-time"
250 #define STATS_OPTION "-stats"
251 #define V_OPTION "-v"
252 #define W_OPTION "-w"
253 #define NDFA_OPTION "-ndfa"
254 #define PROGRESS_OPTION "-progress"
256 /* The following flags are set up by function `initiate_automaton_gen'. */
258 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
259 static int ndfa_flag;
261 /* Do not make minimization of DFA (`-no-minimization'). */
262 static int no_minimization_flag;
264 /* Value of this variable is number of automata being generated. The
265 actual number of automata may be less this value if there is not
266 sufficient number of units. This value is defined by argument of
267 option `-split' or by constructions automaton if the value is zero
268 (it is default value of the argument). */
269 static int split_argument;
271 /* Flag of output time statistics (`-time'). */
272 static int time_flag;
274 /* Flag of automata statistics (`-stats'). */
275 static int stats_flag;
277 /* Flag of creation of description file which contains description of
278 result automaton and statistics information (`-v'). */
279 static int v_flag;
281 /* Flag of output of a progress bar showing how many states were
282 generated so far for automaton being processed (`-progress'). */
283 static int progress_flag;
285 /* Flag of generating warning instead of error for non-critical errors
286 (`-w'). */
287 static int w_flag;
290 /* Output file for pipeline hazard recognizer (PHR) being generated.
291 The value is NULL if the file is not defined. */
292 static FILE *output_file;
294 /* Description file of PHR. The value is NULL if the file is not
295 created. */
296 static FILE *output_description_file;
298 /* PHR description file name. */
299 static char *output_description_file_name;
301 /* Value of the following variable is node representing description
302 being processed. This is start point of IR. */
303 static struct description *description;
307 /* This page contains description of IR structure (nodes). */
309 enum decl_mode
311 dm_unit,
312 dm_bypass,
313 dm_automaton,
314 dm_excl,
315 dm_presence,
316 dm_absence,
317 dm_reserv,
318 dm_insn_reserv
321 /* This describes define_cpu_unit and define_query_cpu_unit (see file
322 rtl.def). */
323 struct unit_decl
325 const char *name;
326 /* NULL if the automaton name is absent. */
327 const char *automaton_name;
328 /* If the following value is not zero, the cpu unit reservation is
329 described in define_query_cpu_unit. */
330 char query_p;
332 /* The following fields are defined by checker. */
334 /* The following field value is nonzero if the unit is used in an
335 regexp. */
336 char unit_is_used;
338 /* The following field value is order number (0, 1, ...) of given
339 unit. */
340 int unit_num;
341 /* The following field value is corresponding declaration of
342 automaton which was given in description. If the field value is
343 NULL then automaton in the unit declaration was absent. */
344 struct automaton_decl *automaton_decl;
345 /* The following field value is maximal cycle number (1, ...) on
346 which given unit occurs in insns. Zero value means that given
347 unit is not used in insns. */
348 int max_occ_cycle_num;
349 /* The following field value is minimal cycle number (0, ...) on
350 which given unit occurs in insns. -1 value means that given
351 unit is not used in insns. */
352 int min_occ_cycle_num;
353 /* The following list contains units which conflict with given
354 unit. */
355 unit_set_el_t excl_list;
356 /* The following list contains patterns which are required to
357 reservation of given unit. */
358 pattern_set_el_t presence_list;
359 pattern_set_el_t final_presence_list;
360 /* The following list contains patterns which should be not present
361 in reservation for given unit. */
362 pattern_set_el_t absence_list;
363 pattern_set_el_t final_absence_list;
364 /* The following is used only when `query_p' has nonzero value.
365 This is query number for the unit. */
366 int query_num;
367 /* The following is the last cycle on which the unit was checked for
368 correct distributions of units to automata in a regexp. */
369 int last_distribution_check_cycle;
371 /* The following fields are defined by automaton generator. */
373 /* The following field value is number of the automaton to which
374 given unit belongs. */
375 int corresponding_automaton_num;
376 /* If the following value is not zero, the cpu unit is present in a
377 `exclusion_set' or in right part of a `presence_set',
378 `final_presence_set', `absence_set', and
379 `final_absence_set'define_query_cpu_unit. */
380 char in_set_p;
383 /* This describes define_bypass (see file rtl.def). */
384 struct bypass_decl
386 int latency;
387 const char *out_insn_name;
388 const char *in_insn_name;
389 const char *bypass_guard_name;
391 /* The following fields are defined by checker. */
393 /* output and input insns of given bypass. */
394 struct insn_reserv_decl *out_insn_reserv;
395 struct insn_reserv_decl *in_insn_reserv;
396 /* The next bypass for given output insn. */
397 struct bypass_decl *next;
400 /* This describes define_automaton (see file rtl.def). */
401 struct automaton_decl
403 const char *name;
405 /* The following fields are defined by automaton generator. */
407 /* The following field value is nonzero if the automaton is used in
408 an regexp definition. */
409 char automaton_is_used;
411 /* The following fields are defined by checker. */
413 /* The following field value is the corresponding automaton. This
414 field is not NULL only if the automaton is present in unit
415 declarations and the automatic partition on automata is not
416 used. */
417 automaton_t corresponding_automaton;
420 /* This describes exclusion relations: exclusion_set (see file
421 rtl.def). */
422 struct excl_rel_decl
424 int all_names_num;
425 int first_list_length;
426 char *names [1];
429 /* This describes unit relations: [final_]presence_set or
430 [final_]absence_set (see file rtl.def). */
431 struct unit_pattern_rel_decl
433 int final_p;
434 int names_num;
435 int patterns_num;
436 char **names;
437 char ***patterns;
440 /* This describes define_reservation (see file rtl.def). */
441 struct reserv_decl
443 const char *name;
444 regexp_t regexp;
446 /* The following fields are defined by checker. */
448 /* The following field value is nonzero if the unit is used in an
449 regexp. */
450 char reserv_is_used;
451 /* The following field is used to check up cycle in expression
452 definition. */
453 int loop_pass_num;
456 /* This describes define_insn_reservation (see file rtl.def). */
457 struct insn_reserv_decl
459 rtx condexp;
460 int default_latency;
461 regexp_t regexp;
462 const char *name;
464 /* The following fields are defined by checker. */
466 /* The following field value is order number (0, 1, ...) of given
467 insn. */
468 int insn_num;
469 /* The following field value is list of bypasses in which given insn
470 is output insn. Bypasses with the same input insn stay one after
471 another in the list in the same order as their occurrences in the
472 description but the bypass without a guard stays always the last
473 in a row of bypasses with the same input insn. */
474 struct bypass_decl *bypass_list;
476 /* The following fields are defined by automaton generator. */
478 /* The following field is the insn regexp transformed that
479 the regexp has not optional regexp, repetition regexp, and an
480 reservation name (i.e. reservation identifiers are changed by the
481 corresponding regexp) and all alternations are the top level
482 of the regexp. The value can be NULL only if it is special
483 insn `cycle advancing'. */
484 regexp_t transformed_regexp;
485 /* The following field value is list of arcs marked given
486 insn. The field is used in transformation NDFA -> DFA. */
487 arc_t arcs_marked_by_insn;
488 /* The two following fields are used during minimization of a finite state
489 automaton. */
490 /* The field value is number of equivalence class of state into
491 which arc marked by given insn enters from a state (fixed during
492 an automaton minimization). */
493 int equiv_class_num;
494 /* The following member value is the list to automata which can be
495 changed by the insn issue. */
496 automata_list_el_t important_automata_list;
497 /* The following member is used to process insn once for output. */
498 int processed_p;
501 /* This contains a declaration mentioned above. */
502 struct decl
504 /* What node in the union? */
505 enum decl_mode mode;
506 pos_t pos;
507 union
509 struct unit_decl unit;
510 struct bypass_decl bypass;
511 struct automaton_decl automaton;
512 struct excl_rel_decl excl;
513 struct unit_pattern_rel_decl presence;
514 struct unit_pattern_rel_decl absence;
515 struct reserv_decl reserv;
516 struct insn_reserv_decl insn_reserv;
517 } decl;
520 /* The following structures represent parsed reservation strings. */
521 enum regexp_mode
523 rm_unit,
524 rm_reserv,
525 rm_nothing,
526 rm_sequence,
527 rm_repeat,
528 rm_allof,
529 rm_oneof
532 /* Cpu unit in reservation. */
533 struct unit_regexp
535 const char *name;
536 unit_decl_t unit_decl;
539 /* Define_reservation in a reservation. */
540 struct reserv_regexp
542 const char *name;
543 struct reserv_decl *reserv_decl;
546 /* Absence of reservation (represented by string `nothing'). */
547 struct nothing_regexp
549 /* This used to be empty but ISO C doesn't allow that. */
550 char unused;
553 /* Representation of reservations separated by ',' (see file
554 rtl.def). */
555 struct sequence_regexp
557 int regexps_num;
558 regexp_t regexps [1];
561 /* Representation of construction `repeat' (see file rtl.def). */
562 struct repeat_regexp
564 int repeat_num;
565 regexp_t regexp;
568 /* Representation of reservations separated by '+' (see file
569 rtl.def). */
570 struct allof_regexp
572 int regexps_num;
573 regexp_t regexps [1];
576 /* Representation of reservations separated by '|' (see file
577 rtl.def). */
578 struct oneof_regexp
580 int regexps_num;
581 regexp_t regexps [1];
584 /* Representation of a reservation string. */
585 struct regexp
587 /* What node in the union? */
588 enum regexp_mode mode;
589 pos_t pos;
590 union
592 struct unit_regexp unit;
593 struct reserv_regexp reserv;
594 struct nothing_regexp nothing;
595 struct sequence_regexp sequence;
596 struct repeat_regexp repeat;
597 struct allof_regexp allof;
598 struct oneof_regexp oneof;
599 } regexp;
602 /* Represents description of pipeline hazard description based on
603 NDFA. */
604 struct description
606 int decls_num;
608 /* The following fields are defined by checker. */
610 /* The following fields values are correspondingly number of all
611 units, query units, and insns in the description. */
612 int units_num;
613 int query_units_num;
614 int insns_num;
615 /* The following field value is max length (in cycles) of
616 reservations of insns. The field value is defined only for
617 correct programs. */
618 int max_insn_reserv_cycles;
620 /* The following fields are defined by automaton generator. */
622 /* The following field value is the first automaton. */
623 automaton_t first_automaton;
625 /* The following field is created by pipeline hazard parser and
626 contains all declarations. We allocate additional entry for
627 special insn "cycle advancing" which is added by the automaton
628 generator. */
629 decl_t decls [1];
633 /* The following nodes are created in automaton checker. */
635 /* The following nodes represent exclusion set for cpu units. Each
636 element is accessed through only one excl_list. */
637 struct unit_set_el
639 unit_decl_t unit_decl;
640 unit_set_el_t next_unit_set_el;
643 /* The following nodes represent presence or absence pattern for cpu
644 units. Each element is accessed through only one presence_list or
645 absence_list. */
646 struct pattern_set_el
648 /* The number of units in unit_decls. */
649 int units_num;
650 /* The units forming the pattern. */
651 struct unit_decl **unit_decls;
652 pattern_set_el_t next_pattern_set_el;
656 /* The following nodes are created in automaton generator. */
659 /* The following nodes represent presence or absence pattern for cpu
660 units. Each element is accessed through only one element of
661 unit_presence_set_table or unit_absence_set_table. */
662 struct pattern_reserv
664 reserv_sets_t reserv;
665 pattern_reserv_t next_pattern_reserv;
668 /* The following node type describes state automaton. The state may
669 be deterministic or non-deterministic. Non-deterministic state has
670 several component states which represent alternative cpu units
671 reservations. The state also is used for describing a
672 deterministic reservation of automaton insn. */
673 struct state
675 /* The following member value is nonzero if there is a transition by
676 cycle advancing. */
677 int new_cycle_p;
678 /* The following field is list of processor unit reservations on
679 each cycle. */
680 reserv_sets_t reservs;
681 /* The following field is unique number of given state between other
682 states. */
683 int unique_num;
684 /* The following field value is automaton to which given state
685 belongs. */
686 automaton_t automaton;
687 /* The following field value is the first arc output from given
688 state. */
689 arc_t first_out_arc;
690 unsigned int num_out_arcs;
691 /* The following field is used to form NDFA. */
692 char it_was_placed_in_stack_for_NDFA_forming;
693 /* The following field is used to form DFA. */
694 char it_was_placed_in_stack_for_DFA_forming;
695 /* The following field is used to transform NDFA to DFA and DFA
696 minimization. The field value is not NULL if the state is a
697 compound state. In this case the value of field `unit_sets_list'
698 is NULL. All states in the list are in the hash table. The list
699 is formed through field `next_sorted_alt_state'. We should
700 support only one level of nesting state. */
701 alt_state_t component_states;
702 /* The following field is used for passing graph of states. */
703 int pass_num;
704 /* The list of states belonging to one equivalence class is formed
705 with the aid of the following field. */
706 state_t next_equiv_class_state;
707 /* The two following fields are used during minimization of a finite
708 state automaton. */
709 int equiv_class_num_1, equiv_class_num_2;
710 /* The following field is used during minimization of a finite state
711 automaton. The field value is state corresponding to equivalence
712 class to which given state belongs. */
713 state_t equiv_class_state;
714 unsigned int *presence_signature;
715 /* The following field value is the order number of given state.
716 The states in final DFA is enumerated with the aid of the
717 following field. */
718 int order_state_num;
719 /* This member is used for passing states for searching minimal
720 delay time. */
721 int state_pass_num;
722 /* The following member is used to evaluate min issue delay of insn
723 for a state. */
724 int min_insn_issue_delay;
727 /* Automaton arc. */
728 struct arc
730 /* The following field refers for the state into which given arc
731 enters. */
732 state_t to_state;
733 /* The following field describes that the insn issue (with cycle
734 advancing for special insn `cycle advancing' and without cycle
735 advancing for others) makes transition from given state to
736 another given state. */
737 ainsn_t insn;
738 /* The following field value is the next arc output from the same
739 state. */
740 arc_t next_out_arc;
741 /* List of arcs marked given insn is formed with the following
742 field. The field is used in transformation NDFA -> DFA. */
743 arc_t next_arc_marked_by_insn;
746 /* The following node type describes a deterministic alternative in
747 non-deterministic state which characterizes cpu unit reservations
748 of automaton insn or which is part of NDFA. */
749 struct alt_state
751 /* The following field is a deterministic state which characterizes
752 unit reservations of the instruction. */
753 state_t state;
754 /* The following field refers to the next state which characterizes
755 unit reservations of the instruction. */
756 alt_state_t next_alt_state;
757 /* The following field refers to the next state in sorted list. */
758 alt_state_t next_sorted_alt_state;
761 /* The following node type describes insn of automaton. They are
762 labels of FA arcs. */
763 struct ainsn
765 /* The following field value is the corresponding insn declaration
766 of description. */
767 struct insn_reserv_decl *insn_reserv_decl;
768 /* The following field value is the next insn declaration for an
769 automaton. */
770 ainsn_t next_ainsn;
771 /* The following field is states which characterize automaton unit
772 reservations of the instruction. The value can be NULL only if it
773 is special insn `cycle advancing'. */
774 alt_state_t alt_states;
775 /* The following field is sorted list of states which characterize
776 automaton unit reservations of the instruction. The value can be
777 NULL only if it is special insn `cycle advancing'. */
778 alt_state_t sorted_alt_states;
779 /* The following field refers the next automaton insn with
780 the same reservations. */
781 ainsn_t next_same_reservs_insn;
782 /* The following field is flag of the first automaton insn with the
783 same reservations in the declaration list. Only arcs marked such
784 insn is present in the automaton. This significantly decreases
785 memory requirements especially when several automata are
786 formed. */
787 char first_insn_with_same_reservs;
788 /* The following member has nonzero value if there is arc from state of
789 the automaton marked by the ainsn. */
790 char arc_exists_p;
791 /* Cyclic list of insns of an equivalence class is formed with the
792 aid of the following field. */
793 ainsn_t next_equiv_class_insn;
794 /* The following field value is nonzero if the insn declaration is
795 the first insn declaration with given equivalence number. */
796 char first_ainsn_with_given_equivalence_num;
797 /* The following field is number of class of equivalence of insns.
798 It is necessary because many insns may be equivalent with the
799 point of view of pipeline hazards. */
800 int insn_equiv_class_num;
801 /* The following member value is TRUE if there is an arc in the
802 automaton marked by the insn into another state. In other
803 words, the insn can change the state of the automaton. */
804 int important_p;
807 /* The following describes an automaton for PHR. */
808 struct automaton
810 /* The following field value is the list of insn declarations for
811 given automaton. */
812 ainsn_t ainsn_list;
813 /* The following field value is the corresponding automaton
814 declaration. This field is not NULL only if the automatic
815 partition on automata is not used. */
816 struct automaton_decl *corresponding_automaton_decl;
817 /* The following field value is the next automaton. */
818 automaton_t next_automaton;
819 /* The following field is start state of FA. There are not unit
820 reservations in the state. */
821 state_t start_state;
822 /* The following field value is number of equivalence classes of
823 insns (see field `insn_equiv_class_num' in
824 `insn_reserv_decl'). */
825 int insn_equiv_classes_num;
826 /* The following field value is number of states of final DFA. */
827 int achieved_states_num;
828 /* The following field value is the order number (0, 1, ...) of
829 given automaton. */
830 int automaton_order_num;
831 /* The following fields contain statistics information about
832 building automaton. */
833 int NDFA_states_num, DFA_states_num;
834 /* The following field value is defined only if minimization of DFA
835 is used. */
836 int minimal_DFA_states_num;
837 int NDFA_arcs_num, DFA_arcs_num;
838 /* The following field value is defined only if minimization of DFA
839 is used. */
840 int minimal_DFA_arcs_num;
841 /* The following member refers for two table state x ainsn -> int.
842 ??? Above sentence is incomprehensible. */
843 state_ainsn_table_t trans_table;
844 /* The following member value is maximal value of min issue delay
845 for insns of the automaton. */
846 int max_min_delay;
847 /* Usually min issue delay is small and we can place several (2, 4,
848 8) elements in one vector element. So the compression factor can
849 be 1 (no compression), 2, 4, 8. */
850 int min_issue_delay_table_compression_factor;
851 /* Total number of locked states in this automaton. */
852 int locked_states;
855 /* The following is the element of the list of automata. */
856 struct automata_list_el
858 /* The automaton itself. */
859 automaton_t automaton;
860 /* The next automata set element. */
861 automata_list_el_t next_automata_list_el;
864 /* The following structure describes a table state X ainsn -> int(>= 0). */
865 struct state_ainsn_table
867 /* Automaton to which given table belongs. */
868 automaton_t automaton;
869 /* The following tree vectors for comb vector implementation of the
870 table. */
871 vla_hwint_t comb_vect;
872 vla_hwint_t check_vect;
873 vla_hwint_t base_vect;
874 /* This is simple implementation of the table. */
875 vla_hwint_t full_vect;
876 /* Minimal and maximal values of the previous vectors. */
877 int min_comb_vect_el_value, max_comb_vect_el_value;
878 int min_base_vect_el_value, max_base_vect_el_value;
881 /* Macros to access members of unions. Use only them for access to
882 union members of declarations and regexps. */
884 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
886 #define DECL_UNIT(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_unit) \
889 decl_mode_check_failed (_decl->mode, "dm_unit", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.unit; }))
893 #define DECL_BYPASS(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_bypass) \
896 decl_mode_check_failed (_decl->mode, "dm_bypass", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.bypass; }))
900 #define DECL_AUTOMATON(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_automaton) \
903 decl_mode_check_failed (_decl->mode, "dm_automaton", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.automaton; }))
907 #define DECL_EXCL(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_excl) \
910 decl_mode_check_failed (_decl->mode, "dm_excl", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.excl; }))
914 #define DECL_PRESENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_presence) \
917 decl_mode_check_failed (_decl->mode, "dm_presence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.presence; }))
921 #define DECL_ABSENCE(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_absence) \
924 decl_mode_check_failed (_decl->mode, "dm_absence", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.absence; }))
928 #define DECL_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.reserv; }))
935 #define DECL_INSN_RESERV(d) __extension__ \
936 (({ __typeof (d) const _decl = (d); \
937 if (_decl->mode != dm_insn_reserv) \
938 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
939 __FILE__, __LINE__, __FUNCTION__); \
940 &(_decl)->decl.insn_reserv; }))
942 static const char *decl_name (enum decl_mode);
943 static void decl_mode_check_failed (enum decl_mode, const char *,
944 const char *, int, const char *)
945 ATTRIBUTE_NORETURN;
947 /* Return string representation of declaration mode MODE. */
948 static const char *
949 decl_name (enum decl_mode mode)
951 static char str [100];
953 if (mode == dm_unit)
954 return "dm_unit";
955 else if (mode == dm_bypass)
956 return "dm_bypass";
957 else if (mode == dm_automaton)
958 return "dm_automaton";
959 else if (mode == dm_excl)
960 return "dm_excl";
961 else if (mode == dm_presence)
962 return "dm_presence";
963 else if (mode == dm_absence)
964 return "dm_absence";
965 else if (mode == dm_reserv)
966 return "dm_reserv";
967 else if (mode == dm_insn_reserv)
968 return "dm_insn_reserv";
969 else
970 sprintf (str, "unknown (%d)", (int) mode);
971 return str;
974 /* The function prints message about unexpected declaration and finish
975 the program. */
976 static void
977 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
978 const char *file, int line, const char *func)
980 fprintf
981 (stderr,
982 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
983 file, line, func, expected_mode_str, decl_name (mode));
984 exit (1);
988 #define REGEXP_UNIT(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_unit) \
991 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.unit; }))
995 #define REGEXP_RESERV(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_reserv) \
998 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.reserv; }))
1002 #define REGEXP_SEQUENCE(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_sequence) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.sequence; }))
1009 #define REGEXP_REPEAT(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_repeat) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.repeat; }))
1016 #define REGEXP_ALLOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_allof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.allof; }))
1023 #define REGEXP_ONEOF(r) __extension__ \
1024 (({ struct regexp *const _regexp = (r); \
1025 if (_regexp->mode != rm_oneof) \
1026 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1027 __FILE__, __LINE__, __FUNCTION__); \
1028 &(_regexp)->regexp.oneof; }))
1030 static const char *regexp_name (enum regexp_mode);
1031 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1032 const char *, int,
1033 const char *) ATTRIBUTE_NORETURN;
1036 /* Return string representation of regexp mode MODE. */
1037 static const char *
1038 regexp_name (enum regexp_mode mode)
1040 switch (mode)
1042 case rm_unit:
1043 return "rm_unit";
1044 case rm_reserv:
1045 return "rm_reserv";
1046 case rm_nothing:
1047 return "rm_nothing";
1048 case rm_sequence:
1049 return "rm_sequence";
1050 case rm_repeat:
1051 return "rm_repeat";
1052 case rm_allof:
1053 return "rm_allof";
1054 case rm_oneof:
1055 return "rm_oneof";
1056 default:
1057 gcc_unreachable ();
1061 /* The function prints message about unexpected regexp and finish the
1062 program. */
1063 static void
1064 regexp_mode_check_failed (enum regexp_mode mode,
1065 const char *expected_mode_str,
1066 const char *file, int line, const char *func)
1068 fprintf
1069 (stderr,
1070 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1071 file, line, func, expected_mode_str, regexp_name (mode));
1072 exit (1);
1075 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1077 #define DECL_UNIT(d) (&(d)->decl.unit)
1078 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1079 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1080 #define DECL_EXCL(d) (&(d)->decl.excl)
1081 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1082 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1083 #define DECL_RESERV(d) (&(d)->decl.reserv)
1084 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1086 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1087 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1088 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1089 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1090 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1091 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1093 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1095 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1096 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1097 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1099 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1100 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1101 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1103 /* Create IR structure (node). */
1104 static void *
1105 create_node (size_t size)
1107 void *result;
1109 obstack_blank (&irp, size);
1110 result = obstack_base (&irp);
1111 obstack_finish (&irp);
1112 /* Default values of members are NULL and zero. */
1113 memset (result, 0, size);
1114 return result;
1117 /* Copy IR structure (node). */
1118 static void *
1119 copy_node (const void *from, size_t size)
1121 void *const result = create_node (size);
1122 memcpy (result, from, size);
1123 return result;
1126 /* The function checks that NAME does not contain quotes (`"'). */
1127 static const char *
1128 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1130 const char *str;
1132 for (str = name; *str != '\0'; str++)
1133 if (*str == '\"')
1134 error ("Name `%s' contains quotes", name);
1135 return name;
1138 /* Pointers to all declarations during IR generation are stored in the
1139 following. */
1140 static VEC(decl_t, heap) *decls;
1142 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1143 string containing the next separated element, taking parentheses
1144 into account if PAR_FLAG has nonzero value. Advance the pointer to
1145 after the string scanned, or the end-of-string. Return NULL if at
1146 end of string. */
1147 static char *
1148 next_sep_el (const char **pstr, int sep, int par_flag)
1150 char *out_str;
1151 const char *p;
1152 int pars_num;
1153 int n_spaces;
1155 /* Remove leading whitespaces. */
1156 while (ISSPACE ((int) **pstr))
1157 (*pstr)++;
1159 if (**pstr == '\0')
1160 return NULL;
1162 n_spaces = 0;
1163 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1165 if (par_flag && *p == '(')
1166 pars_num++;
1167 else if (par_flag && *p == ')')
1168 pars_num--;
1169 else if (pars_num == 0 && *p == sep)
1170 break;
1171 if (pars_num == 0 && ISSPACE ((int) *p))
1172 n_spaces++;
1173 else
1175 for (; n_spaces != 0; n_spaces--)
1176 obstack_1grow (&irp, p [-n_spaces]);
1177 obstack_1grow (&irp, *p);
1180 obstack_1grow (&irp, '\0');
1181 out_str = obstack_base (&irp);
1182 obstack_finish (&irp);
1184 *pstr = p;
1185 if (**pstr == sep)
1186 (*pstr)++;
1188 return out_str;
1191 /* Given a string and a separator, return the number of separated
1192 elements in it, taking parentheses into account if PAR_FLAG has
1193 nonzero value. Return 0 for the null string, -1 if parentheses is
1194 not balanced. */
1195 static int
1196 n_sep_els (const char *s, int sep, int par_flag)
1198 int n;
1199 int pars_num;
1201 if (*s == '\0')
1202 return 0;
1204 for (pars_num = 0, n = 1; *s; s++)
1205 if (par_flag && *s == '(')
1206 pars_num++;
1207 else if (par_flag && *s == ')')
1208 pars_num--;
1209 else if (pars_num == 0 && *s == sep)
1210 n++;
1212 return (pars_num != 0 ? -1 : n);
1215 /* Given a string and a separator, return vector of strings which are
1216 elements in the string and number of elements through els_num.
1217 Take parentheses into account if PAREN_P has nonzero value. The
1218 function also inserts the end marker NULL at the end of vector.
1219 Return 0 for the null string, -1 if parentheses are not balanced. */
1220 static char **
1221 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1223 int i;
1224 char **vect;
1225 const char **pstr;
1226 char *trail;
1228 *els_num = n_sep_els (str, sep, paren_p);
1229 if (*els_num <= 0)
1230 return NULL;
1231 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1232 vect = (char **) obstack_base (&irp);
1233 obstack_finish (&irp);
1234 pstr = &str;
1235 for (i = 0; i < *els_num; i++)
1236 vect [i] = next_sep_el (pstr, sep, paren_p);
1237 trail = next_sep_el (pstr, sep, paren_p);
1238 gcc_assert (!trail);
1239 vect [i] = NULL;
1240 return vect;
1243 /* Process a DEFINE_CPU_UNIT.
1245 This gives information about a unit contained in CPU. We fill a
1246 struct unit_decl with information used later by `expand_automata'. */
1247 static void
1248 gen_cpu_unit (rtx def)
1250 decl_t decl;
1251 char **str_cpu_units;
1252 int vect_length;
1253 int i;
1255 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1256 if (str_cpu_units == NULL)
1257 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1258 for (i = 0; i < vect_length; i++)
1260 decl = XCREATENODE (struct decl);
1261 decl->mode = dm_unit;
1262 decl->pos = 0;
1263 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1264 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1265 DECL_UNIT (decl)->query_p = 0;
1266 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1267 DECL_UNIT (decl)->in_set_p = 0;
1268 VEC_safe_push (decl_t, heap, decls, decl);
1272 /* Process a DEFINE_QUERY_CPU_UNIT.
1274 This gives information about a unit contained in CPU. We fill a
1275 struct unit_decl with information used later by `expand_automata'. */
1276 static void
1277 gen_query_cpu_unit (rtx def)
1279 decl_t decl;
1280 char **str_cpu_units;
1281 int vect_length;
1282 int i;
1284 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1285 FALSE);
1286 if (str_cpu_units == NULL)
1287 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1288 for (i = 0; i < vect_length; i++)
1290 decl = XCREATENODE (struct decl);
1291 decl->mode = dm_unit;
1292 decl->pos = 0;
1293 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1294 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1295 DECL_UNIT (decl)->query_p = 1;
1296 VEC_safe_push (decl_t, heap, decls, decl);
1300 /* Process a DEFINE_BYPASS.
1302 This gives information about a unit contained in the CPU. We fill
1303 in a struct bypass_decl with information used later by
1304 `expand_automata'. */
1305 static void
1306 gen_bypass (rtx def)
1308 decl_t decl;
1309 char **out_insns;
1310 int out_length;
1311 char **in_insns;
1312 int in_length;
1313 int i, j;
1315 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1316 if (out_insns == NULL)
1317 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1318 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1319 if (in_insns == NULL)
1320 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1321 for (i = 0; i < out_length; i++)
1322 for (j = 0; j < in_length; j++)
1324 decl = XCREATENODE (struct decl);
1325 decl->mode = dm_bypass;
1326 decl->pos = 0;
1327 DECL_BYPASS (decl)->latency = XINT (def, 0);
1328 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1329 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1330 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1331 VEC_safe_push (decl_t, heap, decls, decl);
1335 /* Process an EXCLUSION_SET.
1337 This gives information about a cpu unit conflicts. We fill a
1338 struct excl_rel_decl (excl) with information used later by
1339 `expand_automata'. */
1340 static void
1341 gen_excl_set (rtx def)
1343 decl_t decl;
1344 char **first_str_cpu_units;
1345 char **second_str_cpu_units;
1346 int first_vect_length;
1347 int length;
1348 int i;
1350 first_str_cpu_units
1351 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1352 if (first_str_cpu_units == NULL)
1353 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1354 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1355 FALSE);
1356 if (second_str_cpu_units == NULL)
1357 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1358 length += first_vect_length;
1359 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1360 decl->mode = dm_excl;
1361 decl->pos = 0;
1362 DECL_EXCL (decl)->all_names_num = length;
1363 DECL_EXCL (decl)->first_list_length = first_vect_length;
1364 for (i = 0; i < length; i++)
1365 if (i < first_vect_length)
1366 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1367 else
1368 DECL_EXCL (decl)->names [i]
1369 = second_str_cpu_units [i - first_vect_length];
1370 VEC_safe_push (decl_t, heap, decls, decl);
1373 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1374 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1376 This gives information about a cpu unit reservation requirements.
1377 We fill a struct unit_pattern_rel_decl with information used later
1378 by `expand_automata'. */
1379 static void
1380 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1382 decl_t decl;
1383 char **str_cpu_units;
1384 char **str_pattern_lists;
1385 char ***str_patterns;
1386 int cpu_units_length;
1387 int length;
1388 int patterns_length;
1389 int i;
1391 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1392 FALSE);
1393 if (str_cpu_units == NULL)
1394 fatal ((presence_p
1395 ? (final_p
1396 ? "invalid first string `%s' in final_presence_set"
1397 : "invalid first string `%s' in presence_set")
1398 : (final_p
1399 ? "invalid first string `%s' in final_absence_set"
1400 : "invalid first string `%s' in absence_set")),
1401 XSTR (def, 0));
1402 str_pattern_lists = get_str_vect (XSTR (def, 1),
1403 &patterns_length, ',', FALSE);
1404 if (str_pattern_lists == NULL)
1405 fatal ((presence_p
1406 ? (final_p
1407 ? "invalid second string `%s' in final_presence_set"
1408 : "invalid second string `%s' in presence_set")
1409 : (final_p
1410 ? "invalid second string `%s' in final_absence_set"
1411 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1412 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1413 for (i = 0; i < patterns_length; i++)
1415 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1416 &length, ' ', FALSE);
1417 gcc_assert (str_patterns [i]);
1419 decl = XCREATENODE (struct decl);
1420 decl->pos = 0;
1421 if (presence_p)
1423 decl->mode = dm_presence;
1424 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1425 DECL_PRESENCE (decl)->names = str_cpu_units;
1426 DECL_PRESENCE (decl)->patterns = str_patterns;
1427 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1428 DECL_PRESENCE (decl)->final_p = final_p;
1430 else
1432 decl->mode = dm_absence;
1433 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1434 DECL_ABSENCE (decl)->names = str_cpu_units;
1435 DECL_ABSENCE (decl)->patterns = str_patterns;
1436 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1437 DECL_ABSENCE (decl)->final_p = final_p;
1439 VEC_safe_push (decl_t, heap, decls, decl);
1442 /* Process a PRESENCE_SET.
1444 This gives information about a cpu unit reservation requirements.
1445 We fill a struct unit_pattern_rel_decl (presence) with information
1446 used later by `expand_automata'. */
1447 static void
1448 gen_presence_set (rtx def)
1450 gen_presence_absence_set (def, TRUE, FALSE);
1453 /* Process a FINAL_PRESENCE_SET.
1455 This gives information about a cpu unit reservation requirements.
1456 We fill a struct unit_pattern_rel_decl (presence) with information
1457 used later by `expand_automata'. */
1458 static void
1459 gen_final_presence_set (rtx def)
1461 gen_presence_absence_set (def, TRUE, TRUE);
1464 /* Process an ABSENCE_SET.
1466 This gives information about a cpu unit reservation requirements.
1467 We fill a struct unit_pattern_rel_decl (absence) with information
1468 used later by `expand_automata'. */
1469 static void
1470 gen_absence_set (rtx def)
1472 gen_presence_absence_set (def, FALSE, FALSE);
1475 /* Process a FINAL_ABSENCE_SET.
1477 This gives information about a cpu unit reservation requirements.
1478 We fill a struct unit_pattern_rel_decl (absence) with information
1479 used later by `expand_automata'. */
1480 static void
1481 gen_final_absence_set (rtx def)
1483 gen_presence_absence_set (def, FALSE, TRUE);
1486 /* Process a DEFINE_AUTOMATON.
1488 This gives information about a finite state automaton used for
1489 recognizing pipeline hazards. We fill a struct automaton_decl
1490 with information used later by `expand_automata'. */
1491 static void
1492 gen_automaton (rtx def)
1494 decl_t decl;
1495 char **str_automata;
1496 int vect_length;
1497 int i;
1499 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1500 if (str_automata == NULL)
1501 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1502 for (i = 0; i < vect_length; i++)
1504 decl = XCREATENODE (struct decl);
1505 decl->mode = dm_automaton;
1506 decl->pos = 0;
1507 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1508 VEC_safe_push (decl_t, heap, decls, decl);
1512 /* Process an AUTOMATA_OPTION.
1514 This gives information how to generate finite state automaton used
1515 for recognizing pipeline hazards. */
1516 static void
1517 gen_automata_option (rtx def)
1519 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1520 no_minimization_flag = 1;
1521 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1522 time_flag = 1;
1523 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1524 stats_flag = 1;
1525 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1526 v_flag = 1;
1527 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1528 w_flag = 1;
1529 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1530 ndfa_flag = 1;
1531 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1532 progress_flag = 1;
1533 else
1534 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1537 /* Name in reservation to denote absence reservation. */
1538 #define NOTHING_NAME "nothing"
1540 /* The following string contains original reservation string being
1541 parsed. */
1542 static const char *reserv_str;
1544 /* Parse an element in STR. */
1545 static regexp_t
1546 gen_regexp_el (const char *str)
1548 regexp_t regexp;
1549 char *dstr;
1550 int len;
1552 if (*str == '(')
1554 len = strlen (str);
1555 if (str [len - 1] != ')')
1556 fatal ("garbage after ) in reservation `%s'", reserv_str);
1557 dstr = XALLOCAVAR (char, len - 1);
1558 memcpy (dstr, str + 1, len - 2);
1559 dstr [len-2] = '\0';
1560 regexp = gen_regexp_sequence (dstr);
1562 else if (strcmp (str, NOTHING_NAME) == 0)
1564 regexp = XCREATENODE (struct regexp);
1565 regexp->mode = rm_nothing;
1567 else
1569 regexp = XCREATENODE (struct regexp);
1570 regexp->mode = rm_unit;
1571 REGEXP_UNIT (regexp)->name = str;
1573 return regexp;
1576 /* Parse construction `repeat' in STR. */
1577 static regexp_t
1578 gen_regexp_repeat (const char *str)
1580 regexp_t regexp;
1581 regexp_t repeat;
1582 char **repeat_vect;
1583 int els_num;
1584 int i;
1586 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1587 if (repeat_vect == NULL)
1588 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1589 if (els_num > 1)
1591 regexp = gen_regexp_el (repeat_vect [0]);
1592 for (i = 1; i < els_num; i++)
1594 repeat = XCREATENODE (struct regexp);
1595 repeat->mode = rm_repeat;
1596 REGEXP_REPEAT (repeat)->regexp = regexp;
1597 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1598 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1599 fatal ("repetition `%s' <= 1 in reservation `%s'",
1600 str, reserv_str);
1601 regexp = repeat;
1603 return regexp;
1605 else
1606 return gen_regexp_el (str);
1609 /* Parse reservation STR which possibly contains separator '+'. */
1610 static regexp_t
1611 gen_regexp_allof (const char *str)
1613 regexp_t allof;
1614 char **allof_vect;
1615 int els_num;
1616 int i;
1618 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1619 if (allof_vect == NULL)
1620 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1621 if (els_num > 1)
1623 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1624 + sizeof (regexp_t) * (els_num - 1));
1625 allof->mode = rm_allof;
1626 REGEXP_ALLOF (allof)->regexps_num = els_num;
1627 for (i = 0; i < els_num; i++)
1628 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1629 return allof;
1631 else
1632 return gen_regexp_repeat (str);
1635 /* Parse reservation STR which possibly contains separator '|'. */
1636 static regexp_t
1637 gen_regexp_oneof (const char *str)
1639 regexp_t oneof;
1640 char **oneof_vect;
1641 int els_num;
1642 int i;
1644 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1645 if (oneof_vect == NULL)
1646 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1647 if (els_num > 1)
1649 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1650 + sizeof (regexp_t) * (els_num - 1));
1651 oneof->mode = rm_oneof;
1652 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1653 for (i = 0; i < els_num; i++)
1654 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1655 return oneof;
1657 else
1658 return gen_regexp_allof (str);
1661 /* Parse reservation STR which possibly contains separator ','. */
1662 static regexp_t
1663 gen_regexp_sequence (const char *str)
1665 regexp_t sequence;
1666 char **sequence_vect;
1667 int els_num;
1668 int i;
1670 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1671 if (els_num > 1)
1673 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1674 + sizeof (regexp_t) * (els_num - 1));
1675 sequence->mode = rm_sequence;
1676 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1677 for (i = 0; i < els_num; i++)
1678 REGEXP_SEQUENCE (sequence)->regexps [i]
1679 = gen_regexp_oneof (sequence_vect [i]);
1680 return sequence;
1682 else
1683 return gen_regexp_oneof (str);
1686 /* Parse construction reservation STR. */
1687 static regexp_t
1688 gen_regexp (const char *str)
1690 reserv_str = str;
1691 return gen_regexp_sequence (str);;
1694 /* Process a DEFINE_RESERVATION.
1696 This gives information about a reservation of cpu units. We fill
1697 in a struct reserv_decl with information used later by
1698 `expand_automata'. */
1699 static void
1700 gen_reserv (rtx def)
1702 decl_t decl;
1704 decl = XCREATENODE (struct decl);
1705 decl->mode = dm_reserv;
1706 decl->pos = 0;
1707 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1708 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1709 VEC_safe_push (decl_t, heap, decls, decl);
1712 /* Process a DEFINE_INSN_RESERVATION.
1714 This gives information about the reservation of cpu units by an
1715 insn. We fill a struct insn_reserv_decl with information used
1716 later by `expand_automata'. */
1717 static void
1718 gen_insn_reserv (rtx def)
1720 decl_t decl;
1722 decl = XCREATENODE (struct decl);
1723 decl->mode = dm_insn_reserv;
1724 decl->pos = 0;
1725 DECL_INSN_RESERV (decl)->name
1726 = check_name (XSTR (def, 0), decl->pos);
1727 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1728 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1729 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1730 VEC_safe_push (decl_t, heap, decls, decl);
1735 /* The function evaluates hash value (0..UINT_MAX) of string. */
1736 static unsigned
1737 string_hash (const char *string)
1739 unsigned result, i;
1741 for (result = i = 0;*string++ != '\0'; i++)
1742 result += ((unsigned char) *string << (i % CHAR_BIT));
1743 return result;
1748 /* This page contains abstract data `table of automaton declarations'.
1749 Elements of the table is nodes representing automaton declarations.
1750 Key of the table elements is name of given automaton. Remember
1751 that automaton names have own space. */
1753 /* The function evaluates hash value of an automaton declaration. The
1754 function is used by abstract data `hashtab'. The function returns
1755 hash value (0..UINT_MAX) of given automaton declaration. */
1756 static hashval_t
1757 automaton_decl_hash (const void *automaton_decl)
1759 const_decl_t const decl = (const_decl_t) automaton_decl;
1761 gcc_assert (decl->mode != dm_automaton
1762 || DECL_AUTOMATON (decl)->name);
1763 return string_hash (DECL_AUTOMATON (decl)->name);
1766 /* The function tests automaton declarations on equality of their
1767 keys. The function is used by abstract data `hashtab'. The
1768 function returns 1 if the declarations have the same key, 0
1769 otherwise. */
1770 static int
1771 automaton_decl_eq_p (const void* automaton_decl_1,
1772 const void* automaton_decl_2)
1774 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1775 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1777 gcc_assert (decl1->mode == dm_automaton
1778 && DECL_AUTOMATON (decl1)->name
1779 && decl2->mode == dm_automaton
1780 && DECL_AUTOMATON (decl2)->name);
1781 return strcmp (DECL_AUTOMATON (decl1)->name,
1782 DECL_AUTOMATON (decl2)->name) == 0;
1785 /* The automaton declaration table itself is represented by the
1786 following variable. */
1787 static htab_t automaton_decl_table;
1789 /* The function inserts automaton declaration into the table. The
1790 function does nothing if an automaton declaration with the same key
1791 exists already in the table. The function returns automaton
1792 declaration node in the table with the same key as given automaton
1793 declaration node. */
1794 static decl_t
1795 insert_automaton_decl (decl_t automaton_decl)
1797 void **entry_ptr;
1799 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1800 if (*entry_ptr == NULL)
1801 *entry_ptr = (void *) automaton_decl;
1802 return (decl_t) *entry_ptr;
1805 /* The following variable value is node representing automaton
1806 declaration. The node used for searching automaton declaration
1807 with given name. */
1808 static struct decl work_automaton_decl;
1810 /* The function searches for automaton declaration in the table with
1811 the same key as node representing name of the automaton
1812 declaration. The function returns node found in the table, NULL if
1813 such node does not exist in the table. */
1814 static decl_t
1815 find_automaton_decl (const char *name)
1817 void *entry;
1819 work_automaton_decl.mode = dm_automaton;
1820 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1821 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1822 return (decl_t) entry;
1825 /* The function creates empty automaton declaration table and node
1826 representing automaton declaration and used for searching automaton
1827 declaration with given name. The function must be called only once
1828 before any work with the automaton declaration table. */
1829 static void
1830 initiate_automaton_decl_table (void)
1832 work_automaton_decl.mode = dm_automaton;
1833 automaton_decl_table = htab_create (10, automaton_decl_hash,
1834 automaton_decl_eq_p, (htab_del) 0);
1837 /* The function deletes the automaton declaration table. Only call of
1838 function `initiate_automaton_decl_table' is possible immediately
1839 after this function call. */
1840 static void
1841 finish_automaton_decl_table (void)
1843 htab_delete (automaton_decl_table);
1848 /* This page contains abstract data `table of insn declarations'.
1849 Elements of the table is nodes representing insn declarations. Key
1850 of the table elements is name of given insn (in corresponding
1851 define_insn_reservation). Remember that insn names have own
1852 space. */
1854 /* The function evaluates hash value of an insn declaration. The
1855 function is used by abstract data `hashtab'. The function returns
1856 hash value (0..UINT_MAX) of given insn declaration. */
1857 static hashval_t
1858 insn_decl_hash (const void *insn_decl)
1860 const_decl_t const decl = (const_decl_t) insn_decl;
1862 gcc_assert (decl->mode == dm_insn_reserv
1863 && DECL_INSN_RESERV (decl)->name);
1864 return string_hash (DECL_INSN_RESERV (decl)->name);
1867 /* The function tests insn declarations on equality of their keys.
1868 The function is used by abstract data `hashtab'. The function
1869 returns 1 if declarations have the same key, 0 otherwise. */
1870 static int
1871 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1873 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1874 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1876 gcc_assert (decl1->mode == dm_insn_reserv
1877 && DECL_INSN_RESERV (decl1)->name
1878 && decl2->mode == dm_insn_reserv
1879 && DECL_INSN_RESERV (decl2)->name);
1880 return strcmp (DECL_INSN_RESERV (decl1)->name,
1881 DECL_INSN_RESERV (decl2)->name) == 0;
1884 /* The insn declaration table itself is represented by the following
1885 variable. The table does not contain insn reservation
1886 declarations. */
1887 static htab_t insn_decl_table;
1889 /* The function inserts insn declaration into the table. The function
1890 does nothing if an insn declaration with the same key exists
1891 already in the table. The function returns insn declaration node
1892 in the table with the same key as given insn declaration node. */
1893 static decl_t
1894 insert_insn_decl (decl_t insn_decl)
1896 void **entry_ptr;
1898 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1899 if (*entry_ptr == NULL)
1900 *entry_ptr = (void *) insn_decl;
1901 return (decl_t) *entry_ptr;
1904 /* The following variable value is node representing insn reservation
1905 declaration. The node used for searching insn reservation
1906 declaration with given name. */
1907 static struct decl work_insn_decl;
1909 /* The function searches for insn reservation declaration in the table
1910 with the same key as node representing name of the insn reservation
1911 declaration. The function returns node found in the table, NULL if
1912 such node does not exist in the table. */
1913 static decl_t
1914 find_insn_decl (const char *name)
1916 void *entry;
1918 work_insn_decl.mode = dm_insn_reserv;
1919 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1920 entry = htab_find (insn_decl_table, &work_insn_decl);
1921 return (decl_t) entry;
1924 /* The function creates empty insn declaration table and node
1925 representing insn declaration and used for searching insn
1926 declaration with given name. The function must be called only once
1927 before any work with the insn declaration table. */
1928 static void
1929 initiate_insn_decl_table (void)
1931 work_insn_decl.mode = dm_insn_reserv;
1932 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1933 (htab_del) 0);
1936 /* The function deletes the insn declaration table. Only call of
1937 function `initiate_insn_decl_table' is possible immediately after
1938 this function call. */
1939 static void
1940 finish_insn_decl_table (void)
1942 htab_delete (insn_decl_table);
1947 /* This page contains abstract data `table of declarations'. Elements
1948 of the table is nodes representing declarations (of units and
1949 reservations). Key of the table elements is names of given
1950 declarations. */
1952 /* The function evaluates hash value of a declaration. The function
1953 is used by abstract data `hashtab'. The function returns hash
1954 value (0..UINT_MAX) of given declaration. */
1955 static hashval_t
1956 decl_hash (const void *decl)
1958 const_decl_t const d = (const_decl_t) decl;
1960 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1961 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1962 return string_hash (d->mode == dm_unit
1963 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1966 /* The function tests declarations on equality of their keys. The
1967 function is used by abstract data 'hashtab'. The function
1968 returns 1 if the declarations have the same key, 0 otherwise. */
1969 static int
1970 decl_eq_p (const void *decl_1, const void *decl_2)
1972 const_decl_t const d1 = (const_decl_t) decl_1;
1973 const_decl_t const d2 = (const_decl_t) decl_2;
1975 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1976 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1977 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1978 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1979 return strcmp ((d1->mode == dm_unit
1980 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1981 (d2->mode == dm_unit
1982 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1985 /* The declaration table itself is represented by the following
1986 variable. */
1987 static htab_t decl_table;
1989 /* The function inserts declaration into the table. The function does
1990 nothing if a declaration with the same key exists already in the
1991 table. The function returns declaration node in the table with the
1992 same key as given declaration node. */
1994 static decl_t
1995 insert_decl (decl_t decl)
1997 void **entry_ptr;
1999 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2000 if (*entry_ptr == NULL)
2001 *entry_ptr = (void *) decl;
2002 return (decl_t) *entry_ptr;
2005 /* The following variable value is node representing declaration. The
2006 node used for searching declaration with given name. */
2007 static struct decl work_decl;
2009 /* The function searches for declaration in the table with the same
2010 key as node representing name of the declaration. The function
2011 returns node found in the table, NULL if such node does not exist
2012 in the table. */
2013 static decl_t
2014 find_decl (const char *name)
2016 void *entry;
2018 work_decl.mode = dm_unit;
2019 DECL_UNIT (&work_decl)->name = name;
2020 entry = htab_find (decl_table, &work_decl);
2021 return (decl_t) entry;
2024 /* The function creates empty declaration table and node representing
2025 declaration and used for searching declaration with given name.
2026 The function must be called only once before any work with the
2027 declaration table. */
2028 static void
2029 initiate_decl_table (void)
2031 work_decl.mode = dm_unit;
2032 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2035 /* The function deletes the declaration table. Only call of function
2036 `initiate_declaration_table' is possible immediately after this
2037 function call. */
2038 static void
2039 finish_decl_table (void)
2041 htab_delete (decl_table);
2046 /* This page contains checker of pipeline hazard description. */
2048 /* Checking NAMES in an exclusion clause vector and returning formed
2049 unit_set_el_list. */
2050 static unit_set_el_t
2051 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2053 unit_set_el_t el_list;
2054 unit_set_el_t last_el;
2055 unit_set_el_t new_el;
2056 decl_t decl_in_table;
2057 int i;
2059 el_list = NULL;
2060 last_el = NULL;
2061 for (i = 0; i < num; i++)
2063 decl_in_table = find_decl (names [i]);
2064 if (decl_in_table == NULL)
2065 error ("unit `%s' in exclusion is not declared", names [i]);
2066 else if (decl_in_table->mode != dm_unit)
2067 error ("`%s' in exclusion is not unit", names [i]);
2068 else
2070 new_el = XCREATENODE (struct unit_set_el);
2071 new_el->unit_decl = DECL_UNIT (decl_in_table);
2072 new_el->next_unit_set_el = NULL;
2073 if (last_el == NULL)
2074 el_list = last_el = new_el;
2075 else
2077 last_el->next_unit_set_el = new_el;
2078 last_el = last_el->next_unit_set_el;
2082 return el_list;
2085 /* The function adds each element from SOURCE_LIST to the exclusion
2086 list of the each element from DEST_LIST. Checking situation "unit
2087 excludes itself". */
2088 static void
2089 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2090 pos_t excl_pos ATTRIBUTE_UNUSED)
2092 unit_set_el_t dst;
2093 unit_set_el_t src;
2094 unit_set_el_t curr_el;
2095 unit_set_el_t prev_el;
2096 unit_set_el_t copy;
2098 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2099 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2101 if (dst->unit_decl == src->unit_decl)
2103 error ("unit `%s' excludes itself", src->unit_decl->name);
2104 continue;
2106 if (dst->unit_decl->automaton_name != NULL
2107 && src->unit_decl->automaton_name != NULL
2108 && strcmp (dst->unit_decl->automaton_name,
2109 src->unit_decl->automaton_name) != 0)
2111 error ("units `%s' and `%s' in exclusion set belong to different automata",
2112 src->unit_decl->name, dst->unit_decl->name);
2113 continue;
2115 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2116 curr_el != NULL;
2117 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2118 if (curr_el->unit_decl == src->unit_decl)
2119 break;
2120 if (curr_el == NULL)
2122 /* Element not found - insert. */
2123 copy = XCOPYNODE (struct unit_set_el, src);
2124 copy->next_unit_set_el = NULL;
2125 if (prev_el == NULL)
2126 dst->unit_decl->excl_list = copy;
2127 else
2128 prev_el->next_unit_set_el = copy;
2133 /* Checking NAMES in presence/absence clause and returning the
2134 formed unit_set_el_list. The function is called only after
2135 processing all exclusion sets. */
2136 static unit_set_el_t
2137 process_presence_absence_names (char **names, int num,
2138 pos_t req_pos ATTRIBUTE_UNUSED,
2139 int presence_p, int final_p)
2141 unit_set_el_t el_list;
2142 unit_set_el_t last_el;
2143 unit_set_el_t new_el;
2144 decl_t decl_in_table;
2145 int i;
2147 el_list = NULL;
2148 last_el = NULL;
2149 for (i = 0; i < num; i++)
2151 decl_in_table = find_decl (names [i]);
2152 if (decl_in_table == NULL)
2153 error ((presence_p
2154 ? (final_p
2155 ? "unit `%s' in final presence set is not declared"
2156 : "unit `%s' in presence set is not declared")
2157 : (final_p
2158 ? "unit `%s' in final absence set is not declared"
2159 : "unit `%s' in absence set is not declared")), names [i]);
2160 else if (decl_in_table->mode != dm_unit)
2161 error ((presence_p
2162 ? (final_p
2163 ? "`%s' in final presence set is not unit"
2164 : "`%s' in presence set is not unit")
2165 : (final_p
2166 ? "`%s' in final absence set is not unit"
2167 : "`%s' in absence set is not unit")), names [i]);
2168 else
2170 new_el = XCREATENODE (struct unit_set_el);
2171 new_el->unit_decl = DECL_UNIT (decl_in_table);
2172 new_el->next_unit_set_el = NULL;
2173 if (last_el == NULL)
2174 el_list = last_el = new_el;
2175 else
2177 last_el->next_unit_set_el = new_el;
2178 last_el = last_el->next_unit_set_el;
2182 return el_list;
2185 /* Checking NAMES in patterns of a presence/absence clause and
2186 returning the formed pattern_set_el_list. The function is called
2187 only after processing all exclusion sets. */
2188 static pattern_set_el_t
2189 process_presence_absence_patterns (char ***patterns, int num,
2190 pos_t req_pos ATTRIBUTE_UNUSED,
2191 int presence_p, int final_p)
2193 pattern_set_el_t el_list;
2194 pattern_set_el_t last_el;
2195 pattern_set_el_t new_el;
2196 decl_t decl_in_table;
2197 int i, j;
2199 el_list = NULL;
2200 last_el = NULL;
2201 for (i = 0; i < num; i++)
2203 for (j = 0; patterns [i] [j] != NULL; j++)
2205 new_el = XCREATENODEVAR (struct pattern_set_el,
2206 sizeof (struct pattern_set_el)
2207 + sizeof (struct unit_decl *) * j);
2208 new_el->unit_decls
2209 = (struct unit_decl **) ((char *) new_el
2210 + sizeof (struct pattern_set_el));
2211 new_el->next_pattern_set_el = NULL;
2212 if (last_el == NULL)
2213 el_list = last_el = new_el;
2214 else
2216 last_el->next_pattern_set_el = new_el;
2217 last_el = last_el->next_pattern_set_el;
2219 new_el->units_num = 0;
2220 for (j = 0; patterns [i] [j] != NULL; j++)
2222 decl_in_table = find_decl (patterns [i] [j]);
2223 if (decl_in_table == NULL)
2224 error ((presence_p
2225 ? (final_p
2226 ? "unit `%s' in final presence set is not declared"
2227 : "unit `%s' in presence set is not declared")
2228 : (final_p
2229 ? "unit `%s' in final absence set is not declared"
2230 : "unit `%s' in absence set is not declared")),
2231 patterns [i] [j]);
2232 else if (decl_in_table->mode != dm_unit)
2233 error ((presence_p
2234 ? (final_p
2235 ? "`%s' in final presence set is not unit"
2236 : "`%s' in presence set is not unit")
2237 : (final_p
2238 ? "`%s' in final absence set is not unit"
2239 : "`%s' in absence set is not unit")),
2240 patterns [i] [j]);
2241 else
2243 new_el->unit_decls [new_el->units_num]
2244 = DECL_UNIT (decl_in_table);
2245 new_el->units_num++;
2249 return el_list;
2252 /* The function adds each element from PATTERN_LIST to presence (if
2253 PRESENCE_P) or absence list of the each element from DEST_LIST.
2254 Checking situations "unit requires own absence", and "unit excludes
2255 and requires presence of ...", "unit requires absence and presence
2256 of ...", "units in (final) presence set belong to different
2257 automata", and "units in (final) absence set belong to different
2258 automata". Remember that we process absence sets only after all
2259 presence sets. */
2260 static void
2261 add_presence_absence (unit_set_el_t dest_list,
2262 pattern_set_el_t pattern_list,
2263 pos_t req_pos ATTRIBUTE_UNUSED,
2264 int presence_p, int final_p)
2266 unit_set_el_t dst;
2267 pattern_set_el_t pat;
2268 struct unit_decl *unit;
2269 unit_set_el_t curr_excl_el;
2270 pattern_set_el_t curr_pat_el;
2271 pattern_set_el_t prev_el;
2272 pattern_set_el_t copy;
2273 int i;
2274 int no_error_flag;
2276 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2277 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2279 for (i = 0; i < pat->units_num; i++)
2281 unit = pat->unit_decls [i];
2282 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2284 error ("unit `%s' requires own absence", unit->name);
2285 continue;
2287 if (dst->unit_decl->automaton_name != NULL
2288 && unit->automaton_name != NULL
2289 && strcmp (dst->unit_decl->automaton_name,
2290 unit->automaton_name) != 0)
2292 error ((presence_p
2293 ? (final_p
2294 ? "units `%s' and `%s' in final presence set belong to different automata"
2295 : "units `%s' and `%s' in presence set belong to different automata")
2296 : (final_p
2297 ? "units `%s' and `%s' in final absence set belong to different automata"
2298 : "units `%s' and `%s' in absence set belong to different automata")),
2299 unit->name, dst->unit_decl->name);
2300 continue;
2302 no_error_flag = 1;
2303 if (presence_p)
2304 for (curr_excl_el = dst->unit_decl->excl_list;
2305 curr_excl_el != NULL;
2306 curr_excl_el = curr_excl_el->next_unit_set_el)
2308 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2310 if (!w_flag)
2312 error ("unit `%s' excludes and requires presence of `%s'",
2313 dst->unit_decl->name, unit->name);
2314 no_error_flag = 0;
2316 else
2317 warning ("unit `%s' excludes and requires presence of `%s'",
2318 dst->unit_decl->name, unit->name);
2321 else if (pat->units_num == 1)
2322 for (curr_pat_el = dst->unit_decl->presence_list;
2323 curr_pat_el != NULL;
2324 curr_pat_el = curr_pat_el->next_pattern_set_el)
2325 if (curr_pat_el->units_num == 1
2326 && unit == curr_pat_el->unit_decls [0])
2328 if (!w_flag)
2330 error ("unit `%s' requires absence and presence of `%s'",
2331 dst->unit_decl->name, unit->name);
2332 no_error_flag = 0;
2334 else
2335 warning ("unit `%s' requires absence and presence of `%s'",
2336 dst->unit_decl->name, unit->name);
2338 if (no_error_flag)
2340 for (prev_el = (presence_p
2341 ? (final_p
2342 ? dst->unit_decl->final_presence_list
2343 : dst->unit_decl->final_presence_list)
2344 : (final_p
2345 ? dst->unit_decl->final_absence_list
2346 : dst->unit_decl->absence_list));
2347 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2348 prev_el = prev_el->next_pattern_set_el)
2350 copy = XCOPYNODE (struct pattern_set_el, pat);
2351 copy->next_pattern_set_el = NULL;
2352 if (prev_el == NULL)
2354 if (presence_p)
2356 if (final_p)
2357 dst->unit_decl->final_presence_list = copy;
2358 else
2359 dst->unit_decl->presence_list = copy;
2361 else if (final_p)
2362 dst->unit_decl->final_absence_list = copy;
2363 else
2364 dst->unit_decl->absence_list = copy;
2366 else
2367 prev_el->next_pattern_set_el = copy;
2374 /* The function inserts BYPASS in the list of bypasses of the
2375 corresponding output insn. The order of bypasses in the list is
2376 decribed in a comment for member `bypass_list' (see above). If
2377 there is already the same bypass in the list the function reports
2378 this and does nothing. */
2379 static void
2380 insert_bypass (struct bypass_decl *bypass)
2382 struct bypass_decl *curr, *last;
2383 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2384 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2386 for (curr = out_insn_reserv->bypass_list, last = NULL;
2387 curr != NULL;
2388 last = curr, curr = curr->next)
2389 if (curr->in_insn_reserv == in_insn_reserv)
2391 if ((bypass->bypass_guard_name != NULL
2392 && curr->bypass_guard_name != NULL
2393 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2394 || bypass->bypass_guard_name == curr->bypass_guard_name)
2396 if (bypass->bypass_guard_name == NULL)
2398 if (!w_flag)
2399 error ("the same bypass `%s - %s' is already defined",
2400 bypass->out_insn_name, bypass->in_insn_name);
2401 else
2402 warning ("the same bypass `%s - %s' is already defined",
2403 bypass->out_insn_name, bypass->in_insn_name);
2405 else if (!w_flag)
2406 error ("the same bypass `%s - %s' (guard %s) is already defined",
2407 bypass->out_insn_name, bypass->in_insn_name,
2408 bypass->bypass_guard_name);
2409 else
2410 warning
2411 ("the same bypass `%s - %s' (guard %s) is already defined",
2412 bypass->out_insn_name, bypass->in_insn_name,
2413 bypass->bypass_guard_name);
2414 return;
2416 if (curr->bypass_guard_name == NULL)
2417 break;
2418 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2420 last = curr;
2421 break;
2425 if (last == NULL)
2427 bypass->next = out_insn_reserv->bypass_list;
2428 out_insn_reserv->bypass_list = bypass;
2430 else
2432 bypass->next = last->next;
2433 last->next = bypass;
2437 /* The function processes pipeline description declarations, checks
2438 their correctness, and forms exclusion/presence/absence sets. */
2439 static void
2440 process_decls (void)
2442 decl_t decl;
2443 decl_t automaton_decl;
2444 decl_t decl_in_table;
2445 decl_t out_insn_reserv;
2446 decl_t in_insn_reserv;
2447 int automaton_presence;
2448 int i;
2450 /* Checking repeated automata declarations. */
2451 automaton_presence = 0;
2452 for (i = 0; i < description->decls_num; i++)
2454 decl = description->decls [i];
2455 if (decl->mode == dm_automaton)
2457 automaton_presence = 1;
2458 decl_in_table = insert_automaton_decl (decl);
2459 if (decl_in_table != decl)
2461 if (!w_flag)
2462 error ("repeated declaration of automaton `%s'",
2463 DECL_AUTOMATON (decl)->name);
2464 else
2465 warning ("repeated declaration of automaton `%s'",
2466 DECL_AUTOMATON (decl)->name);
2470 /* Checking undeclared automata, repeated declarations (except for
2471 automata) and correctness of their attributes (insn latency times
2472 etc.). */
2473 for (i = 0; i < description->decls_num; i++)
2475 decl = description->decls [i];
2476 if (decl->mode == dm_insn_reserv)
2478 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2479 error ("define_insn_reservation `%s' has negative latency time",
2480 DECL_INSN_RESERV (decl)->name);
2481 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2482 description->insns_num++;
2483 decl_in_table = insert_insn_decl (decl);
2484 if (decl_in_table != decl)
2485 error ("`%s' is already used as insn reservation name",
2486 DECL_INSN_RESERV (decl)->name);
2488 else if (decl->mode == dm_bypass)
2490 if (DECL_BYPASS (decl)->latency < 0)
2491 error ("define_bypass `%s - %s' has negative latency time",
2492 DECL_BYPASS (decl)->out_insn_name,
2493 DECL_BYPASS (decl)->in_insn_name);
2495 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2497 if (decl->mode == dm_unit)
2499 DECL_UNIT (decl)->automaton_decl = NULL;
2500 if (DECL_UNIT (decl)->automaton_name != NULL)
2502 automaton_decl
2503 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2504 if (automaton_decl == NULL)
2505 error ("automaton `%s' is not declared",
2506 DECL_UNIT (decl)->automaton_name);
2507 else
2509 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2510 DECL_UNIT (decl)->automaton_decl
2511 = DECL_AUTOMATON (automaton_decl);
2514 else if (automaton_presence)
2515 error ("define_unit `%s' without automaton when one defined",
2516 DECL_UNIT (decl)->name);
2517 DECL_UNIT (decl)->unit_num = description->units_num;
2518 description->units_num++;
2519 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2521 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2522 continue;
2524 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2526 else
2528 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2530 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2531 continue;
2533 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2535 if (decl_in_table == NULL)
2536 decl_in_table = insert_decl (decl);
2537 else
2539 if (decl->mode == dm_unit)
2540 error ("repeated declaration of unit `%s'",
2541 DECL_UNIT (decl)->name);
2542 else
2543 error ("repeated declaration of reservation `%s'",
2544 DECL_RESERV (decl)->name);
2548 /* Check bypasses and form list of bypasses for each (output)
2549 insn. */
2550 for (i = 0; i < description->decls_num; i++)
2552 decl = description->decls [i];
2553 if (decl->mode == dm_bypass)
2555 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2556 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2557 if (out_insn_reserv == NULL)
2558 error ("there is no insn reservation `%s'",
2559 DECL_BYPASS (decl)->out_insn_name);
2560 else if (in_insn_reserv == NULL)
2561 error ("there is no insn reservation `%s'",
2562 DECL_BYPASS (decl)->in_insn_name);
2563 else
2565 DECL_BYPASS (decl)->out_insn_reserv
2566 = DECL_INSN_RESERV (out_insn_reserv);
2567 DECL_BYPASS (decl)->in_insn_reserv
2568 = DECL_INSN_RESERV (in_insn_reserv);
2569 insert_bypass (DECL_BYPASS (decl));
2574 /* Check exclusion set declarations and form exclusion sets. */
2575 for (i = 0; i < description->decls_num; i++)
2577 decl = description->decls [i];
2578 if (decl->mode == dm_excl)
2580 unit_set_el_t unit_set_el_list;
2581 unit_set_el_t unit_set_el_list_2;
2583 unit_set_el_list
2584 = process_excls (DECL_EXCL (decl)->names,
2585 DECL_EXCL (decl)->first_list_length, decl->pos);
2586 unit_set_el_list_2
2587 = process_excls (&DECL_EXCL (decl)->names
2588 [DECL_EXCL (decl)->first_list_length],
2589 DECL_EXCL (decl)->all_names_num
2590 - DECL_EXCL (decl)->first_list_length,
2591 decl->pos);
2592 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2593 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2597 /* Check presence set declarations and form presence sets. */
2598 for (i = 0; i < description->decls_num; i++)
2600 decl = description->decls [i];
2601 if (decl->mode == dm_presence)
2603 unit_set_el_t unit_set_el_list;
2604 pattern_set_el_t pattern_set_el_list;
2606 unit_set_el_list
2607 = process_presence_absence_names
2608 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2609 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2610 pattern_set_el_list
2611 = process_presence_absence_patterns
2612 (DECL_PRESENCE (decl)->patterns,
2613 DECL_PRESENCE (decl)->patterns_num,
2614 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2615 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2616 decl->pos, TRUE,
2617 DECL_PRESENCE (decl)->final_p);
2621 /* Check absence set declarations and form absence sets. */
2622 for (i = 0; i < description->decls_num; i++)
2624 decl = description->decls [i];
2625 if (decl->mode == dm_absence)
2627 unit_set_el_t unit_set_el_list;
2628 pattern_set_el_t pattern_set_el_list;
2630 unit_set_el_list
2631 = process_presence_absence_names
2632 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2633 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2634 pattern_set_el_list
2635 = process_presence_absence_patterns
2636 (DECL_ABSENCE (decl)->patterns,
2637 DECL_ABSENCE (decl)->patterns_num,
2638 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2639 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2640 decl->pos, FALSE,
2641 DECL_ABSENCE (decl)->final_p);
2646 /* The following function checks that declared automaton is used. If
2647 the automaton is not used, the function fixes error/warning. The
2648 following function must be called only after `process_decls'. */
2649 static void
2650 check_automaton_usage (void)
2652 decl_t decl;
2653 int i;
2655 for (i = 0; i < description->decls_num; i++)
2657 decl = description->decls [i];
2658 if (decl->mode == dm_automaton
2659 && !DECL_AUTOMATON (decl)->automaton_is_used)
2661 if (!w_flag)
2662 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2663 else
2664 warning ("automaton `%s' is not used",
2665 DECL_AUTOMATON (decl)->name);
2670 /* The following recursive function processes all regexp in order to
2671 fix usage of units or reservations and to fix errors of undeclared
2672 name. The function may change unit_regexp onto reserv_regexp.
2673 Remember that reserv_regexp does not exist before the function
2674 call. */
2675 static regexp_t
2676 process_regexp (regexp_t regexp)
2678 decl_t decl_in_table;
2679 regexp_t new_regexp;
2680 int i;
2682 switch (regexp->mode)
2684 case rm_unit:
2685 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2686 if (decl_in_table == NULL)
2687 error ("undeclared unit or reservation `%s'",
2688 REGEXP_UNIT (regexp)->name);
2689 else
2690 switch (decl_in_table->mode)
2692 case dm_unit:
2693 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2694 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2695 break;
2697 case dm_reserv:
2698 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2699 new_regexp = XCREATENODE (struct regexp);
2700 new_regexp->mode = rm_reserv;
2701 new_regexp->pos = regexp->pos;
2702 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2703 REGEXP_RESERV (new_regexp)->reserv_decl
2704 = DECL_RESERV (decl_in_table);
2705 regexp = new_regexp;
2706 break;
2708 default:
2709 gcc_unreachable ();
2711 break;
2712 case rm_sequence:
2713 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2714 REGEXP_SEQUENCE (regexp)->regexps [i]
2715 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2716 break;
2717 case rm_allof:
2718 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2719 REGEXP_ALLOF (regexp)->regexps [i]
2720 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2721 break;
2722 case rm_oneof:
2723 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2724 REGEXP_ONEOF (regexp)->regexps [i]
2725 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2726 break;
2727 case rm_repeat:
2728 REGEXP_REPEAT (regexp)->regexp
2729 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2730 break;
2731 case rm_nothing:
2732 break;
2733 default:
2734 gcc_unreachable ();
2736 return regexp;
2739 /* The following function processes regexp of define_reservation and
2740 define_insn_reservation with the aid of function
2741 `process_regexp'. */
2742 static void
2743 process_regexp_decls (void)
2745 decl_t decl;
2746 int i;
2748 for (i = 0; i < description->decls_num; i++)
2750 decl = description->decls [i];
2751 if (decl->mode == dm_reserv)
2752 DECL_RESERV (decl)->regexp
2753 = process_regexp (DECL_RESERV (decl)->regexp);
2754 else if (decl->mode == dm_insn_reserv)
2755 DECL_INSN_RESERV (decl)->regexp
2756 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2760 /* The following function checks that declared unit is used. If the
2761 unit is not used, the function fixes errors/warnings. The
2762 following function must be called only after `process_decls',
2763 `process_regexp_decls'. */
2764 static void
2765 check_usage (void)
2767 decl_t decl;
2768 int i;
2770 for (i = 0; i < description->decls_num; i++)
2772 decl = description->decls [i];
2773 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2775 if (!w_flag)
2776 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2777 else
2778 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2780 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2782 if (!w_flag)
2783 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2784 else
2785 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2790 /* The following variable value is number of reservation being
2791 processed on loop recognition. */
2792 static int curr_loop_pass_num;
2794 /* The following recursive function returns nonzero value if REGEXP
2795 contains given decl or reservations in given regexp refers for
2796 given decl. */
2797 static int
2798 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2800 int i;
2802 if (regexp == NULL)
2803 return 0;
2804 switch (regexp->mode)
2806 case rm_unit:
2807 return 0;
2809 case rm_reserv:
2810 if (start_decl->mode == dm_reserv
2811 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2812 return 1;
2813 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2814 == curr_loop_pass_num)
2815 /* declaration has been processed. */
2816 return 0;
2817 else
2819 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2820 = curr_loop_pass_num;
2821 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2822 start_decl);
2825 case rm_sequence:
2826 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2827 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2828 return 1;
2829 return 0;
2831 case rm_allof:
2832 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2833 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2834 return 1;
2835 return 0;
2837 case rm_oneof:
2838 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2839 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2840 return 1;
2841 return 0;
2843 case rm_repeat:
2844 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2846 case rm_nothing:
2847 return 0;
2849 default:
2850 gcc_unreachable ();
2854 /* The following function fixes errors "cycle in definition ...". The
2855 function uses function `loop_in_regexp' for that. */
2856 static void
2857 check_loops_in_regexps (void)
2859 decl_t decl;
2860 int i;
2862 for (i = 0; i < description->decls_num; i++)
2864 decl = description->decls [i];
2865 if (decl->mode == dm_reserv)
2866 DECL_RESERV (decl)->loop_pass_num = 0;
2868 for (i = 0; i < description->decls_num; i++)
2870 decl = description->decls [i];
2871 curr_loop_pass_num = i;
2873 if (decl->mode == dm_reserv)
2875 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2876 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2878 gcc_assert (DECL_RESERV (decl)->regexp);
2879 error ("cycle in definition of reservation `%s'",
2880 DECL_RESERV (decl)->name);
2886 /* The function recursively processes IR of reservation and defines
2887 max and min cycle for reservation of unit. */
2888 static void
2889 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2890 int min_start_cycle, int *max_finish_cycle,
2891 int *min_finish_cycle)
2893 int i;
2895 switch (regexp->mode)
2897 case rm_unit:
2898 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2899 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2900 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2901 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2902 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2903 *max_finish_cycle = max_start_cycle;
2904 *min_finish_cycle = min_start_cycle;
2905 break;
2907 case rm_reserv:
2908 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2909 max_start_cycle, min_start_cycle,
2910 max_finish_cycle, min_finish_cycle);
2911 break;
2913 case rm_repeat:
2914 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2916 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2917 max_start_cycle, min_start_cycle,
2918 max_finish_cycle, min_finish_cycle);
2919 max_start_cycle = *max_finish_cycle + 1;
2920 min_start_cycle = *min_finish_cycle + 1;
2922 break;
2924 case rm_sequence:
2925 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2927 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2928 max_start_cycle, min_start_cycle,
2929 max_finish_cycle, min_finish_cycle);
2930 max_start_cycle = *max_finish_cycle + 1;
2931 min_start_cycle = *min_finish_cycle + 1;
2933 break;
2935 case rm_allof:
2937 int max_cycle = 0;
2938 int min_cycle = 0;
2940 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2942 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2943 max_start_cycle, min_start_cycle,
2944 max_finish_cycle, min_finish_cycle);
2945 if (max_cycle < *max_finish_cycle)
2946 max_cycle = *max_finish_cycle;
2947 if (i == 0 || min_cycle > *min_finish_cycle)
2948 min_cycle = *min_finish_cycle;
2950 *max_finish_cycle = max_cycle;
2951 *min_finish_cycle = min_cycle;
2953 break;
2955 case rm_oneof:
2957 int max_cycle = 0;
2958 int min_cycle = 0;
2960 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2962 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2963 max_start_cycle, min_start_cycle,
2964 max_finish_cycle, min_finish_cycle);
2965 if (max_cycle < *max_finish_cycle)
2966 max_cycle = *max_finish_cycle;
2967 if (i == 0 || min_cycle > *min_finish_cycle)
2968 min_cycle = *min_finish_cycle;
2970 *max_finish_cycle = max_cycle;
2971 *min_finish_cycle = min_cycle;
2973 break;
2975 case rm_nothing:
2976 *max_finish_cycle = max_start_cycle;
2977 *min_finish_cycle = min_start_cycle;
2978 break;
2980 default:
2981 gcc_unreachable ();
2985 /* The following function is called only for correct program. The
2986 function defines max reservation of insns in cycles. */
2987 static void
2988 evaluate_max_reserv_cycles (void)
2990 int max_insn_cycles_num;
2991 int min_insn_cycles_num;
2992 decl_t decl;
2993 int i;
2995 description->max_insn_reserv_cycles = 0;
2996 for (i = 0; i < description->decls_num; i++)
2998 decl = description->decls [i];
2999 if (decl->mode == dm_insn_reserv)
3001 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3002 &max_insn_cycles_num, &min_insn_cycles_num);
3003 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3004 description->max_insn_reserv_cycles = max_insn_cycles_num;
3007 description->max_insn_reserv_cycles++;
3010 /* The following function calls functions for checking all
3011 description. */
3012 static void
3013 check_all_description (void)
3015 process_decls ();
3016 check_automaton_usage ();
3017 process_regexp_decls ();
3018 check_usage ();
3019 check_loops_in_regexps ();
3020 if (!have_error)
3021 evaluate_max_reserv_cycles ();
3026 /* The page contains abstract data `ticker'. This data is used to
3027 report time of different phases of building automata. It is
3028 possibly to write a description for which automata will be built
3029 during several minutes even on fast machine. */
3031 /* The following function creates ticker and makes it active. */
3032 static ticker_t
3033 create_ticker (void)
3035 ticker_t ticker;
3037 ticker.modified_creation_time = get_run_time ();
3038 ticker.incremented_off_time = 0;
3039 return ticker;
3042 /* The following function switches off given ticker. */
3043 static void
3044 ticker_off (ticker_t *ticker)
3046 if (ticker->incremented_off_time == 0)
3047 ticker->incremented_off_time = get_run_time () + 1;
3050 /* The following function switches on given ticker. */
3051 static void
3052 ticker_on (ticker_t *ticker)
3054 if (ticker->incremented_off_time != 0)
3056 ticker->modified_creation_time
3057 += get_run_time () - ticker->incremented_off_time + 1;
3058 ticker->incremented_off_time = 0;
3062 /* The following function returns current time in milliseconds since
3063 the moment when given ticker was created. */
3064 static int
3065 active_time (ticker_t ticker)
3067 if (ticker.incremented_off_time != 0)
3068 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3069 else
3070 return get_run_time () - ticker.modified_creation_time;
3073 /* The following function returns string representation of active time
3074 of given ticker. The result is string representation of seconds
3075 with accuracy of 1/100 second. Only result of the last call of the
3076 function exists. Therefore the following code is not correct
3078 printf ("parser time: %s\ngeneration time: %s\n",
3079 active_time_string (parser_ticker),
3080 active_time_string (generation_ticker));
3082 Correct code has to be the following
3084 printf ("parser time: %s\n", active_time_string (parser_ticker));
3085 printf ("generation time: %s\n",
3086 active_time_string (generation_ticker));
3089 static void
3090 print_active_time (FILE *f, ticker_t ticker)
3092 int msecs;
3094 msecs = active_time (ticker);
3095 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3100 /* The following variable value is number of automaton which are
3101 really being created. This value is defined on the base of
3102 argument of option `-split'. If the variable has zero value the
3103 number of automata is defined by the constructions `%automaton'.
3104 This case occurs when option `-split' is absent or has zero
3105 argument. If constructions `define_automaton' is absent only one
3106 automaton is created. */
3107 static int automata_num;
3109 /* The following variable values are times of
3110 o transformation of regular expressions
3111 o building NDFA (DFA if !ndfa_flag)
3112 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3113 o DFA minimization
3114 o building insn equivalence classes
3115 o all previous ones
3116 o code output */
3117 static ticker_t transform_time;
3118 static ticker_t NDFA_time;
3119 static ticker_t NDFA_to_DFA_time;
3120 static ticker_t minimize_time;
3121 static ticker_t equiv_time;
3122 static ticker_t automaton_generation_time;
3123 static ticker_t output_time;
3125 /* The following variable values are times of
3126 all checking
3127 all generation
3128 all pipeline hazard translator work */
3129 static ticker_t check_time;
3130 static ticker_t generation_time;
3131 static ticker_t all_time;
3135 /* Pseudo insn decl which denotes advancing cycle. */
3136 static decl_t advance_cycle_insn_decl;
3137 static void
3138 add_advance_cycle_insn_decl (void)
3140 advance_cycle_insn_decl = XCREATENODE (struct decl);
3141 advance_cycle_insn_decl->mode = dm_insn_reserv;
3142 advance_cycle_insn_decl->pos = no_pos;
3143 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3144 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3145 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3146 = description->insns_num;
3147 description->decls [description->decls_num] = advance_cycle_insn_decl;
3148 description->decls_num++;
3149 description->insns_num++;
3153 /* Abstract data `alternative states' which represents
3154 nondeterministic nature of the description (see comments for
3155 structures alt_state and state). */
3157 /* List of free states. */
3158 static alt_state_t first_free_alt_state;
3160 #ifndef NDEBUG
3161 /* The following variables is maximal number of allocated nodes
3162 alt_state. */
3163 static int allocated_alt_states_num = 0;
3164 #endif
3166 /* The following function returns free node alt_state. It may be new
3167 allocated node or node freed earlier. */
3168 static alt_state_t
3169 get_free_alt_state (void)
3171 alt_state_t result;
3173 if (first_free_alt_state != NULL)
3175 result = first_free_alt_state;
3176 first_free_alt_state = first_free_alt_state->next_alt_state;
3178 else
3180 #ifndef NDEBUG
3181 allocated_alt_states_num++;
3182 #endif
3183 result = XCREATENODE (struct alt_state);
3185 result->state = NULL;
3186 result->next_alt_state = NULL;
3187 result->next_sorted_alt_state = NULL;
3188 return result;
3191 /* The function frees node ALT_STATE. */
3192 static void
3193 free_alt_state (alt_state_t alt_state)
3195 if (alt_state == NULL)
3196 return;
3197 alt_state->next_alt_state = first_free_alt_state;
3198 first_free_alt_state = alt_state;
3201 /* The function frees list started with node ALT_STATE_LIST. */
3202 static void
3203 free_alt_states (alt_state_t alt_states_list)
3205 alt_state_t curr_alt_state;
3206 alt_state_t next_alt_state;
3208 for (curr_alt_state = alt_states_list;
3209 curr_alt_state != NULL;
3210 curr_alt_state = next_alt_state)
3212 next_alt_state = curr_alt_state->next_alt_state;
3213 free_alt_state (curr_alt_state);
3217 /* The function compares unique numbers of alt states. */
3218 static int
3219 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3221 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3222 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3223 return 0;
3224 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3225 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3226 return -1;
3227 else
3228 return 1;
3231 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3232 states from the list. The comparison key is alt state unique
3233 number. */
3235 static alt_state_t
3236 uniq_sort_alt_states (alt_state_t alt_states_list)
3238 alt_state_t curr_alt_state;
3239 VEC(alt_state_t, heap) *alt_states;
3240 size_t i;
3241 size_t prev_unique_state_ind;
3242 alt_state_t result;
3244 if (alt_states_list == 0)
3245 return 0;
3246 if (alt_states_list->next_alt_state == 0)
3247 return alt_states_list;
3249 alt_states = VEC_alloc (alt_state_t, heap, 150);
3250 for (curr_alt_state = alt_states_list;
3251 curr_alt_state != NULL;
3252 curr_alt_state = curr_alt_state->next_alt_state)
3253 VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state);
3255 qsort (VEC_address (alt_state_t, alt_states),
3256 VEC_length (alt_state_t, alt_states),
3257 sizeof (alt_state_t), alt_state_cmp);
3259 prev_unique_state_ind = 0;
3260 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3261 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3262 != VEC_index (alt_state_t, alt_states, i)->state)
3264 prev_unique_state_ind++;
3265 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3266 VEC_index (alt_state_t, alt_states, i));
3268 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3270 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3271 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3272 = VEC_index (alt_state_t, alt_states, i);
3273 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3275 result = VEC_index (alt_state_t, alt_states, 0);
3277 VEC_free (alt_state_t, heap, alt_states);
3278 return result;
3281 /* The function checks equality of alt state lists. Remember that the
3282 lists must be already sorted by the previous function. */
3283 static int
3284 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3286 while (alt_states_1 != NULL && alt_states_2 != NULL
3287 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3289 alt_states_1 = alt_states_1->next_sorted_alt_state;
3290 alt_states_2 = alt_states_2->next_sorted_alt_state;
3292 return alt_states_1 == alt_states_2;
3295 /* Initialization of the abstract data. */
3296 static void
3297 initiate_alt_states (void)
3299 first_free_alt_state = NULL;
3302 /* Finishing work with the abstract data. */
3303 static void
3304 finish_alt_states (void)
3310 /* The page contains macros for work with bits strings. We could use
3311 standard gcc bitmap or sbitmap but it would result in difficulties
3312 of building canadian cross. */
3314 /* Set bit number bitno in the bit string. The macro is not side
3315 effect proof. */
3316 #define SET_BIT(bitstring, bitno) \
3317 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3318 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3320 #define CLEAR_BIT(bitstring, bitno) \
3321 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3322 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3324 /* Test if bit number bitno in the bitstring is set. The macro is not
3325 side effect proof. */
3326 #define TEST_BIT(bitstring, bitno) \
3327 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3328 (bitno) % (sizeof (*(bitstring)) * 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, INSERT);
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, INSERT);
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 el;
4181 unsigned int i;
4182 int start_unit_num;
4183 int unit_num;
4185 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4186 for (el = 0; el < els_in_cycle_reserv; el++)
4187 if (in_set[el])
4188 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4189 if ((in_set[el] >> i) & 1)
4191 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4192 if (start_unit_num >= description->units_num)
4193 return excl_set;
4194 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4196 excl_set [unit_num]
4197 |= unit_excl_set_table [start_unit_num] [unit_num];
4200 return excl_set;
4205 /* The page contains abstract data for work with presence/absence
4206 pattern sets (see presence_set/absence_set in file rtl.def). */
4208 /* The following arrays contain correspondingly presence, final
4209 presence, absence, and final absence patterns for each unit. */
4210 static pattern_reserv_t *unit_presence_set_table;
4211 static pattern_reserv_t *unit_final_presence_set_table;
4212 static pattern_reserv_t *unit_absence_set_table;
4213 static pattern_reserv_t *unit_final_absence_set_table;
4215 /* The following function forms list of reservation sets for given
4216 PATTERN_LIST. */
4217 static pattern_reserv_t
4218 form_reserv_sets_list (pattern_set_el_t pattern_list)
4220 pattern_set_el_t el;
4221 pattern_reserv_t first, curr, prev;
4222 int i;
4224 prev = first = NULL;
4225 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4227 curr = XCREATENODE (struct pattern_reserv);
4228 curr->reserv = alloc_empty_reserv_sets ();
4229 curr->next_pattern_reserv = NULL;
4230 for (i = 0; i < el->units_num; i++)
4232 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4233 el->unit_decls [i]->in_set_p = TRUE;
4235 if (prev != NULL)
4236 prev->next_pattern_reserv = curr;
4237 else
4238 first = curr;
4239 prev = curr;
4241 return first;
4244 /* The following function forms the array containing presence and
4245 absence pattern sets for each unit. */
4246 static void
4247 initiate_presence_absence_pattern_sets (void)
4249 decl_t decl;
4250 int i;
4252 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4253 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4254 obstack_finish (&irp);
4255 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4256 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4257 obstack_finish (&irp);
4258 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4259 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4260 obstack_finish (&irp);
4261 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4262 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4263 obstack_finish (&irp);
4264 /* Evaluate unit presence/absence sets. */
4265 for (i = 0; i < description->decls_num; i++)
4267 decl = description->decls [i];
4268 if (decl->mode == dm_unit)
4270 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4271 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4272 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4273 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4274 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4275 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4276 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4277 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4282 /* The function checks that CHECKED_SET satisfies all presence pattern
4283 sets for units in ORIGINAL_SET. The function returns TRUE if it
4284 is ok. */
4285 static int
4286 check_presence_pattern_sets (reserv_sets_t checked_set,
4287 reserv_sets_t original_set,
4288 int final_p)
4290 int el;
4291 unsigned int i;
4292 int start_unit_num;
4293 int unit_num;
4294 int presence_p;
4295 pattern_reserv_t pat_reserv;
4297 for (el = 0; el < els_in_cycle_reserv; el++)
4298 if (original_set[el])
4299 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4300 if ((original_set[el] >> i) & 1)
4302 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4303 if (start_unit_num >= description->units_num)
4304 break;
4305 if ((final_p
4306 && unit_final_presence_set_table [start_unit_num] == NULL)
4307 || (!final_p
4308 && unit_presence_set_table [start_unit_num] == NULL))
4309 continue;
4310 presence_p = FALSE;
4311 for (pat_reserv = (final_p
4312 ? unit_final_presence_set_table [start_unit_num]
4313 : unit_presence_set_table [start_unit_num]);
4314 pat_reserv != NULL;
4315 pat_reserv = pat_reserv->next_pattern_reserv)
4317 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4318 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4319 != pat_reserv->reserv [unit_num])
4320 break;
4321 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4323 if (!presence_p)
4324 return FALSE;
4326 return TRUE;
4329 /* The function checks that CHECKED_SET satisfies all absence pattern
4330 sets for units in ORIGINAL_SET. The function returns TRUE if it
4331 is ok. */
4332 static int
4333 check_absence_pattern_sets (reserv_sets_t checked_set,
4334 reserv_sets_t original_set,
4335 int final_p)
4337 int el;
4338 unsigned int i;
4339 int start_unit_num;
4340 int unit_num;
4341 pattern_reserv_t pat_reserv;
4343 for (el = 0; el < els_in_cycle_reserv; el++)
4344 if (original_set[el])
4345 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4346 if ((original_set[el] >> i) & 1)
4348 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4349 if (start_unit_num >= description->units_num)
4350 break;
4351 for (pat_reserv = (final_p
4352 ? unit_final_absence_set_table [start_unit_num]
4353 : unit_absence_set_table [start_unit_num]);
4354 pat_reserv != NULL;
4355 pat_reserv = pat_reserv->next_pattern_reserv)
4357 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4358 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4359 != pat_reserv->reserv [unit_num]
4360 && pat_reserv->reserv [unit_num])
4361 break;
4362 if (unit_num >= els_in_cycle_reserv)
4363 return FALSE;
4366 return TRUE;
4371 /* This page contains code for transformation of original reservations
4372 described in .md file. The main goal of transformations is
4373 simplifying reservation and lifting up all `|' on the top of IR
4374 reservation representation. */
4377 /* The following function makes copy of IR representation of
4378 reservation. The function also substitutes all reservations
4379 defined by define_reservation by corresponding value during making
4380 the copy. */
4381 static regexp_t
4382 copy_insn_regexp (regexp_t regexp)
4384 regexp_t result;
4385 int i;
4387 switch (regexp->mode)
4389 case rm_reserv:
4390 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4391 break;
4393 case rm_unit:
4394 result = XCOPYNODE (struct regexp, regexp);
4395 break;
4397 case rm_repeat:
4398 result = XCOPYNODE (struct regexp, regexp);
4399 REGEXP_REPEAT (result)->regexp
4400 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4401 break;
4403 case rm_sequence:
4404 result = XCOPYNODEVAR (struct regexp, regexp,
4405 sizeof (struct regexp) + sizeof (regexp_t)
4406 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4407 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4408 REGEXP_SEQUENCE (result)->regexps [i]
4409 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4410 break;
4412 case rm_allof:
4413 result = XCOPYNODEVAR (struct regexp, regexp,
4414 sizeof (struct regexp) + sizeof (regexp_t)
4415 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4416 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4417 REGEXP_ALLOF (result)->regexps [i]
4418 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4419 break;
4421 case rm_oneof:
4422 result = XCOPYNODEVAR (struct regexp, regexp,
4423 sizeof (struct regexp) + sizeof (regexp_t)
4424 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4425 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4426 REGEXP_ONEOF (result)->regexps [i]
4427 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4428 break;
4430 case rm_nothing:
4431 result = XCOPYNODE (struct regexp, regexp);
4432 break;
4434 default:
4435 gcc_unreachable ();
4437 return result;
4440 /* The following variable is set up 1 if a transformation has been
4441 applied. */
4442 static int regexp_transformed_p;
4444 /* The function makes transformation
4445 A*N -> A, A, ... */
4446 static regexp_t
4447 transform_1 (regexp_t regexp)
4449 int i;
4450 int repeat_num;
4451 regexp_t operand;
4452 pos_t pos;
4454 if (regexp->mode == rm_repeat)
4456 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4457 gcc_assert (repeat_num > 1);
4458 operand = REGEXP_REPEAT (regexp)->regexp;
4459 pos = regexp->mode;
4460 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4461 + sizeof (regexp_t) * (repeat_num - 1));
4462 regexp->mode = rm_sequence;
4463 regexp->pos = pos;
4464 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4465 for (i = 0; i < repeat_num; i++)
4466 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4467 regexp_transformed_p = 1;
4469 return regexp;
4472 /* The function makes transformations
4473 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4474 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4475 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4476 static regexp_t
4477 transform_2 (regexp_t regexp)
4479 if (regexp->mode == rm_sequence)
4481 regexp_t sequence = NULL;
4482 regexp_t result;
4483 int sequence_index = 0;
4484 int i, j;
4486 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4487 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4489 sequence_index = i;
4490 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4491 break;
4493 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4495 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4496 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4497 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4498 + sizeof (regexp_t)
4499 * (REGEXP_SEQUENCE (regexp)->regexps_num
4500 + REGEXP_SEQUENCE (sequence)->regexps_num
4501 - 2));
4502 result->mode = rm_sequence;
4503 result->pos = regexp->pos;
4504 REGEXP_SEQUENCE (result)->regexps_num
4505 = (REGEXP_SEQUENCE (regexp)->regexps_num
4506 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4507 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4508 if (i < sequence_index)
4509 REGEXP_SEQUENCE (result)->regexps [i]
4510 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4511 else if (i > sequence_index)
4512 REGEXP_SEQUENCE (result)->regexps
4513 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4514 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4515 else
4516 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4517 REGEXP_SEQUENCE (result)->regexps [i + j]
4518 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4519 regexp_transformed_p = 1;
4520 regexp = result;
4523 else if (regexp->mode == rm_allof)
4525 regexp_t allof = NULL;
4526 regexp_t result;
4527 int allof_index = 0;
4528 int i, j;
4530 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4531 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4533 allof_index = i;
4534 allof = REGEXP_ALLOF (regexp)->regexps [i];
4535 break;
4537 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4539 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4540 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4541 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4542 + sizeof (regexp_t)
4543 * (REGEXP_ALLOF (regexp)->regexps_num
4544 + REGEXP_ALLOF (allof)->regexps_num - 2));
4545 result->mode = rm_allof;
4546 result->pos = regexp->pos;
4547 REGEXP_ALLOF (result)->regexps_num
4548 = (REGEXP_ALLOF (regexp)->regexps_num
4549 + REGEXP_ALLOF (allof)->regexps_num - 1);
4550 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4551 if (i < allof_index)
4552 REGEXP_ALLOF (result)->regexps [i]
4553 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4554 else if (i > allof_index)
4555 REGEXP_ALLOF (result)->regexps
4556 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4557 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4558 else
4559 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4560 REGEXP_ALLOF (result)->regexps [i + j]
4561 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4562 regexp_transformed_p = 1;
4563 regexp = result;
4566 else if (regexp->mode == rm_oneof)
4568 regexp_t oneof = NULL;
4569 regexp_t result;
4570 int oneof_index = 0;
4571 int i, j;
4573 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4574 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4576 oneof_index = i;
4577 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4578 break;
4580 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4582 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4583 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4584 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4585 + sizeof (regexp_t)
4586 * (REGEXP_ONEOF (regexp)->regexps_num
4587 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4588 result->mode = rm_oneof;
4589 result->pos = regexp->pos;
4590 REGEXP_ONEOF (result)->regexps_num
4591 = (REGEXP_ONEOF (regexp)->regexps_num
4592 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4593 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4594 if (i < oneof_index)
4595 REGEXP_ONEOF (result)->regexps [i]
4596 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4597 else if (i > oneof_index)
4598 REGEXP_ONEOF (result)->regexps
4599 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4600 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4601 else
4602 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4603 REGEXP_ONEOF (result)->regexps [i + j]
4604 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4605 regexp_transformed_p = 1;
4606 regexp = result;
4609 return regexp;
4612 /* The function makes transformations
4613 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4614 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4615 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4616 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4617 static regexp_t
4618 transform_3 (regexp_t regexp)
4620 if (regexp->mode == rm_sequence)
4622 regexp_t oneof = NULL;
4623 int oneof_index = 0;
4624 regexp_t result;
4625 regexp_t sequence;
4626 int i, j;
4628 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4629 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4631 oneof_index = i;
4632 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4633 break;
4635 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4637 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4638 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4639 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4640 + sizeof (regexp_t)
4641 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4642 result->mode = rm_oneof;
4643 result->pos = regexp->pos;
4644 REGEXP_ONEOF (result)->regexps_num
4645 = REGEXP_ONEOF (oneof)->regexps_num;
4646 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4648 sequence
4649 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4650 + sizeof (regexp_t)
4651 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4652 sequence->mode = rm_sequence;
4653 sequence->pos = regexp->pos;
4654 REGEXP_SEQUENCE (sequence)->regexps_num
4655 = REGEXP_SEQUENCE (regexp)->regexps_num;
4656 REGEXP_ONEOF (result)->regexps [i] = sequence;
4657 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4658 if (j != oneof_index)
4659 REGEXP_SEQUENCE (sequence)->regexps [j]
4660 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4661 else
4662 REGEXP_SEQUENCE (sequence)->regexps [j]
4663 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4665 regexp_transformed_p = 1;
4666 regexp = result;
4669 else if (regexp->mode == rm_allof)
4671 regexp_t oneof = NULL;
4672 regexp_t seq;
4673 int oneof_index = 0;
4674 int max_seq_length, allof_length;
4675 regexp_t result;
4676 regexp_t allof = NULL;
4677 regexp_t allof_op = NULL;
4678 int i, j;
4680 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4681 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4683 oneof_index = i;
4684 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4685 break;
4687 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4689 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4690 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4691 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4692 + sizeof (regexp_t)
4693 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4694 result->mode = rm_oneof;
4695 result->pos = regexp->pos;
4696 REGEXP_ONEOF (result)->regexps_num
4697 = REGEXP_ONEOF (oneof)->regexps_num;
4698 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4700 allof
4701 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4702 + sizeof (regexp_t)
4703 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4704 allof->mode = rm_allof;
4705 allof->pos = regexp->pos;
4706 REGEXP_ALLOF (allof)->regexps_num
4707 = REGEXP_ALLOF (regexp)->regexps_num;
4708 REGEXP_ONEOF (result)->regexps [i] = allof;
4709 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4710 if (j != oneof_index)
4711 REGEXP_ALLOF (allof)->regexps [j]
4712 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4713 else
4714 REGEXP_ALLOF (allof)->regexps [j]
4715 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4717 regexp_transformed_p = 1;
4718 regexp = result;
4720 max_seq_length = 0;
4721 if (regexp->mode == rm_allof)
4722 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4724 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4726 case rm_sequence:
4727 seq = REGEXP_ALLOF (regexp)->regexps [i];
4728 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4729 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4730 break;
4732 case rm_unit:
4733 case rm_nothing:
4734 break;
4736 default:
4737 max_seq_length = 0;
4738 goto break_for;
4741 break_for:
4742 if (max_seq_length != 0)
4744 gcc_assert (max_seq_length != 1
4745 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4746 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4747 + sizeof (regexp_t) * (max_seq_length - 1));
4748 result->mode = rm_sequence;
4749 result->pos = regexp->pos;
4750 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4751 for (i = 0; i < max_seq_length; i++)
4753 allof_length = 0;
4754 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4755 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4757 case rm_sequence:
4758 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4759 ->regexps [j])->regexps_num))
4761 allof_op
4762 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4763 ->regexps [j])
4764 ->regexps [i]);
4765 allof_length++;
4767 break;
4768 case rm_unit:
4769 case rm_nothing:
4770 if (i == 0)
4772 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4773 allof_length++;
4775 break;
4776 default:
4777 break;
4780 if (allof_length == 1)
4781 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4782 else
4784 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4785 + sizeof (regexp_t)
4786 * (allof_length - 1));
4787 allof->mode = rm_allof;
4788 allof->pos = regexp->pos;
4789 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4790 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4791 allof_length = 0;
4792 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4793 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4794 && (i <
4795 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4796 ->regexps [j])->regexps_num)))
4798 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4799 ->regexps [j])
4800 ->regexps [i]);
4801 REGEXP_ALLOF (allof)->regexps [allof_length]
4802 = allof_op;
4803 allof_length++;
4805 else if (i == 0
4806 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4807 == rm_unit
4808 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4809 == rm_nothing)))
4811 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4812 REGEXP_ALLOF (allof)->regexps [allof_length]
4813 = allof_op;
4814 allof_length++;
4818 regexp_transformed_p = 1;
4819 regexp = result;
4822 return regexp;
4825 /* The function traverses IR of reservation and applies transformations
4826 implemented by FUNC. */
4827 static regexp_t
4828 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4830 int i;
4832 switch (regexp->mode)
4834 case rm_sequence:
4835 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4836 REGEXP_SEQUENCE (regexp)->regexps [i]
4837 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4838 func);
4839 break;
4841 case rm_allof:
4842 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4843 REGEXP_ALLOF (regexp)->regexps [i]
4844 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4845 break;
4847 case rm_oneof:
4848 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4849 REGEXP_ONEOF (regexp)->regexps [i]
4850 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4851 break;
4853 case rm_repeat:
4854 REGEXP_REPEAT (regexp)->regexp
4855 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4856 break;
4858 case rm_nothing:
4859 case rm_unit:
4860 break;
4862 default:
4863 gcc_unreachable ();
4865 return (*func) (regexp);
4868 /* The function applies all transformations for IR representation of
4869 reservation REGEXP. */
4870 static regexp_t
4871 transform_regexp (regexp_t regexp)
4873 regexp = regexp_transform_func (regexp, transform_1);
4876 regexp_transformed_p = 0;
4877 regexp = regexp_transform_func (regexp, transform_2);
4878 regexp = regexp_transform_func (regexp, transform_3);
4880 while (regexp_transformed_p);
4881 return regexp;
4884 /* The function applies all transformations for reservations of all
4885 insn declarations. */
4886 static void
4887 transform_insn_regexps (void)
4889 decl_t decl;
4890 int i;
4892 transform_time = create_ticker ();
4893 add_advance_cycle_insn_decl ();
4894 if (progress_flag)
4895 fprintf (stderr, "Reservation transformation...");
4896 for (i = 0; i < description->decls_num; i++)
4898 decl = description->decls [i];
4899 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4900 DECL_INSN_RESERV (decl)->transformed_regexp
4901 = transform_regexp (copy_insn_regexp
4902 (DECL_INSN_RESERV (decl)->regexp));
4904 if (progress_flag)
4905 fprintf (stderr, "done\n");
4906 ticker_off (&transform_time);
4911 /* The following variable value is TRUE if the first annotated message
4912 about units to automata distribution has been output. */
4913 static int annotation_message_reported_p;
4915 /* The vector contains all decls which are automata. */
4916 static VEC(decl_t, heap) *automaton_decls;
4918 /* The following structure describes usage of a unit in a reservation. */
4919 struct unit_usage
4921 unit_decl_t unit_decl;
4922 /* The following forms a list of units used on the same cycle in the
4923 same alternative. The list is ordered by the correspdoning unit
4924 declarations and there is no unit declaration duplication in the
4925 list. */
4926 struct unit_usage *next;
4928 typedef struct unit_usage *unit_usage_t;
4930 DEF_VEC_P(unit_usage_t);
4931 DEF_VEC_ALLOC_P(unit_usage_t, heap);
4933 /* Obstack for unit_usage structures. */
4934 static struct obstack unit_usages;
4936 /* VLA for representation of array of pointers to unit usage
4937 structures. There is an element for each combination of
4938 (alternative number, cycle). Unit usages on given cycle in
4939 alternative with given number are referred through element with
4940 index equals to the cycle * number of all alternatives in the
4941 regexp + the alternative number. */
4942 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
4944 /* The following function creates the structure unit_usage for UNIT on
4945 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4946 accessed through cycle_alt_unit_usages. */
4947 static void
4948 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4949 int alt_num)
4951 size_t length;
4952 unit_decl_t unit_decl;
4953 unit_usage_t unit_usage_ptr, curr, prev;
4954 int index;
4956 gcc_assert (regexp && regexp->mode == rm_oneof
4957 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4958 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4960 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4961 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4962 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0);
4964 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4965 prev = NULL;
4966 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4967 curr != NULL;
4968 prev = curr, curr = curr->next)
4969 if (curr->unit_decl >= unit_decl)
4970 break;
4971 if (curr != NULL && curr->unit_decl == unit_decl)
4972 return;
4973 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4974 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4975 obstack_finish (&unit_usages);
4976 unit_usage_ptr->unit_decl = unit_decl;
4977 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4978 unit_usage_ptr->next = curr;
4979 if (prev == NULL)
4980 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4981 else
4982 prev->next = unit_usage_ptr;
4985 /* Return true if unit UNIT_DECL is present on the LIST. */
4986 static bool
4987 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
4989 while (list != NULL)
4991 if (list->unit_decl == unit_decl)
4992 return true;
4993 list = list->next;
4995 return false;
4998 /* The function returns true if reservations of alternatives ALT1 and
4999 ALT2 are equal after excluding reservations of units of
5000 EXCLUDED_AUTOMATON_DECL. */
5001 static bool
5002 equal_alternatives_p (int alt1, int alt2, int n_alts,
5003 struct automaton_decl *excluded_automaton_decl)
5005 int i;
5006 unit_usage_t list1, list2;
5008 for (i = 0;
5009 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5010 i += n_alts)
5012 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5013 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5014 list1 = list1->next, list2 = list2->next)
5016 while (list1 != NULL
5017 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5018 list1 = list1->next;
5019 while (list2 != NULL
5020 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5021 list2 = list2->next;
5022 if (list1 == NULL || list2 == NULL)
5024 if (list1 != list2)
5025 return false;
5026 else
5027 break;
5029 if (list1->unit_decl != list2->unit_decl)
5030 return false;
5033 return true;
5036 DEF_VEC_I(int);
5037 DEF_VEC_ALLOC_I(int, heap);
5039 /* The function processes given REGEXP to find units with the wrong
5040 distribution. */
5041 static void
5042 check_regexp_units_distribution (const char *insn_reserv_name,
5043 regexp_t regexp)
5045 int i, j, k, cycle, start, n_alts, alt, alt2;
5046 bool annotation_reservation_message_reported_p;
5047 regexp_t seq, allof, unit;
5048 struct unit_usage *unit_usage_ptr;
5049 VEC(int, heap) *marked;
5051 if (regexp == NULL || regexp->mode != rm_oneof)
5052 return;
5053 /* Store all unit usages in the regexp: */
5054 obstack_init (&unit_usages);
5055 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5057 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5059 seq = REGEXP_ONEOF (regexp)->regexps [i];
5060 switch (seq->mode)
5062 case rm_sequence:
5063 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5065 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5066 switch (allof->mode)
5068 case rm_allof:
5069 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5071 unit = REGEXP_ALLOF (allof)->regexps [k];
5072 if (unit->mode == rm_unit)
5073 store_alt_unit_usage (regexp, unit, j, i);
5074 else
5075 gcc_assert (unit->mode == rm_nothing);
5077 break;
5079 case rm_unit:
5080 store_alt_unit_usage (regexp, allof, j, i);
5081 break;
5083 case rm_nothing:
5084 break;
5086 default:
5087 gcc_unreachable ();
5090 break;
5092 case rm_allof:
5093 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5095 unit = REGEXP_ALLOF (seq)->regexps [k];
5096 switch (unit->mode)
5098 case rm_unit:
5099 store_alt_unit_usage (regexp, unit, 0, i);
5100 break;
5102 case rm_nothing:
5103 break;
5105 default:
5106 gcc_unreachable ();
5109 break;
5111 case rm_unit:
5112 store_alt_unit_usage (regexp, seq, 0, i);
5113 break;
5115 case rm_nothing:
5116 break;
5118 default:
5119 gcc_unreachable ();
5122 /* Check distribution: */
5123 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5124 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5125 unit_usage_ptr != NULL;
5126 unit_usage_ptr = unit_usage_ptr->next)
5127 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5128 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5129 marked = VEC_alloc (int, heap, n_alts);
5130 for (i = 0; i < n_alts; i++)
5131 VEC_safe_push (int, heap, marked, 0);
5132 annotation_reservation_message_reported_p = false;
5133 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5135 cycle = i / n_alts;
5136 start = cycle * n_alts;
5137 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5138 unit_usage_ptr != NULL;
5139 unit_usage_ptr = unit_usage_ptr->next)
5141 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5142 continue;
5143 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5144 for (alt = 0; alt < n_alts; alt++)
5145 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5146 cycle_alt_unit_usages,
5147 start + alt),
5148 unit_usage_ptr->unit_decl))
5149 break;
5150 if (alt >= n_alts)
5151 continue;
5152 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5153 for (alt = 0; alt < n_alts; alt++)
5155 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5156 cycle_alt_unit_usages,
5157 start + alt),
5158 unit_usage_ptr->unit_decl))
5159 continue;
5160 for (j = 0;
5161 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5162 j++)
5164 alt2 = j % n_alts;
5165 if (! unit_present_on_list_p
5166 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5167 start + alt2),
5168 unit_usage_ptr->unit_decl)
5169 && equal_alternatives_p (alt, alt2, n_alts,
5170 unit_usage_ptr
5171 ->unit_decl->automaton_decl))
5173 VEC_replace (int, marked, alt, 1);
5174 VEC_replace (int, marked, alt2, 1);
5178 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5180 if (alt < n_alts && 0)
5182 if (! annotation_message_reported_p)
5184 fprintf (stderr, "\n");
5185 error ("The following units do not satisfy units-automata distribution rule");
5186 error ("(Unit presence on one alt and its absence on other alt\n");
5187 error (" result in different other automata reservations)");
5188 annotation_message_reported_p = TRUE;
5190 if (! annotation_reservation_message_reported_p)
5192 error ("Reserv %s:", insn_reserv_name);
5193 annotation_reservation_message_reported_p = true;
5195 error (" Unit %s, cycle %d, alt %d, another alt %d",
5196 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5200 VEC_free (int, heap, marked);
5201 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5202 obstack_free (&unit_usages, NULL);
5205 /* The function finds units which violates units to automata
5206 distribution rule. If the units exist, report about them. */
5207 static void
5208 check_unit_distributions_to_automata (void)
5210 decl_t decl;
5211 int i;
5213 if (progress_flag)
5214 fprintf (stderr, "Check unit distributions to automata...");
5215 automaton_decls = NULL;
5216 for (i = 0; i < description->decls_num; i++)
5218 decl = description->decls [i];
5219 if (decl->mode == dm_automaton)
5220 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5222 if (VEC_length (decl_t, automaton_decls) > 1)
5224 annotation_message_reported_p = FALSE;
5225 for (i = 0; i < description->decls_num; i++)
5227 decl = description->decls [i];
5228 if (decl->mode == dm_insn_reserv)
5229 check_regexp_units_distribution
5230 (DECL_INSN_RESERV (decl)->name,
5231 DECL_INSN_RESERV (decl)->transformed_regexp);
5234 VEC_free (decl_t, heap, automaton_decls);
5235 if (progress_flag)
5236 fprintf (stderr, "done\n");
5241 /* The page contains code for building alt_states (see comments for
5242 IR) describing all possible insns reservations of an automaton. */
5244 /* Current state being formed for which the current alt_state
5245 refers. */
5246 static state_t state_being_formed;
5248 /* Current alt_state being formed. */
5249 static alt_state_t alt_state_being_formed;
5251 /* This recursive function processes `,' and units in reservation
5252 REGEXP for forming alt_states of AUTOMATON. It is believed that
5253 CURR_CYCLE is start cycle of all reservation REGEXP. */
5254 static int
5255 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5256 int curr_cycle)
5258 int i;
5260 if (regexp == NULL)
5261 return curr_cycle;
5263 switch (regexp->mode)
5265 case rm_unit:
5266 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5267 == automaton->automaton_order_num)
5268 set_state_reserv (state_being_formed, curr_cycle,
5269 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5270 return curr_cycle;
5272 case rm_sequence:
5273 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5274 curr_cycle
5275 = process_seq_for_forming_states
5276 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5277 return curr_cycle;
5279 case rm_allof:
5281 int finish_cycle = 0;
5282 int cycle;
5284 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5286 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5287 ->regexps [i],
5288 automaton, curr_cycle);
5289 if (finish_cycle < cycle)
5290 finish_cycle = cycle;
5292 return finish_cycle;
5295 case rm_nothing:
5296 return curr_cycle;
5298 default:
5299 gcc_unreachable ();
5303 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5304 inserts alt_state into the table. */
5305 static void
5306 finish_forming_alt_state (alt_state_t alt_state,
5307 automaton_t automaton ATTRIBUTE_UNUSED)
5309 state_t state_in_table;
5310 state_t corresponding_state;
5312 corresponding_state = alt_state->state;
5313 state_in_table = insert_state (corresponding_state);
5314 if (state_in_table != corresponding_state)
5316 free_state (corresponding_state);
5317 alt_state->state = state_in_table;
5321 /* The following variable value is current automaton insn for whose
5322 reservation the alt states are created. */
5323 static ainsn_t curr_ainsn;
5325 /* This recursive function processes `|' in reservation REGEXP for
5326 forming alt_states of AUTOMATON. List of the alt states should
5327 have the same order as in the description. */
5328 static void
5329 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5330 int inside_oneof_p)
5332 int i;
5334 if (regexp->mode != rm_oneof)
5336 alt_state_being_formed = get_free_alt_state ();
5337 state_being_formed = get_free_state (1, automaton);
5338 alt_state_being_formed->state = state_being_formed;
5339 /* We inserts in reverse order but we process alternatives also
5340 in reverse order. So we have the same order of alternative
5341 as in the description. */
5342 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5343 curr_ainsn->alt_states = alt_state_being_formed;
5344 (void) process_seq_for_forming_states (regexp, automaton, 0);
5345 finish_forming_alt_state (alt_state_being_formed, automaton);
5347 else
5349 gcc_assert (!inside_oneof_p);
5350 /* We processes it in reverse order to get list with the same
5351 order as in the description. See also the previous
5352 commentary. */
5353 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5354 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5355 automaton, 1);
5359 /* Create nodes alt_state for all AUTOMATON insns. */
5360 static void
5361 create_alt_states (automaton_t automaton)
5363 struct insn_reserv_decl *reserv_decl;
5365 for (curr_ainsn = automaton->ainsn_list;
5366 curr_ainsn != NULL;
5367 curr_ainsn = curr_ainsn->next_ainsn)
5369 reserv_decl = curr_ainsn->insn_reserv_decl;
5370 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5372 curr_ainsn->alt_states = NULL;
5373 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5374 automaton, 0);
5375 curr_ainsn->sorted_alt_states
5376 = uniq_sort_alt_states (curr_ainsn->alt_states);
5383 /* The page contains major code for building DFA(s) for fast pipeline
5384 hazards recognition. */
5386 /* The function forms list of ainsns of AUTOMATON with the same
5387 reservation. */
5389 static void
5390 form_ainsn_with_same_reservs (automaton_t automaton)
5392 ainsn_t curr_ainsn;
5393 size_t i;
5394 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5396 for (curr_ainsn = automaton->ainsn_list;
5397 curr_ainsn != NULL;
5398 curr_ainsn = curr_ainsn->next_ainsn)
5399 if (curr_ainsn->insn_reserv_decl
5400 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5402 curr_ainsn->next_same_reservs_insn = NULL;
5403 curr_ainsn->first_insn_with_same_reservs = 1;
5405 else
5407 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5408 if (alt_states_eq
5409 (curr_ainsn->sorted_alt_states,
5410 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5411 break;
5412 curr_ainsn->next_same_reservs_insn = NULL;
5413 if (i < VEC_length (ainsn_t, last_insns))
5415 curr_ainsn->first_insn_with_same_reservs = 0;
5416 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5417 = curr_ainsn;
5418 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5420 else
5422 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5423 curr_ainsn->first_insn_with_same_reservs = 1;
5426 VEC_free (ainsn_t, heap, last_insns);
5429 /* Forming unit reservations which can affect creating the automaton
5430 states achieved from a given state. It permits to build smaller
5431 automata in many cases. We would have the same automata after
5432 the minimization without such optimization, but the automaton
5433 right after the building could be huge. So in other words, usage
5434 of reservs_matter means some minimization during building the
5435 automaton. */
5436 static reserv_sets_t
5437 form_reservs_matter (automaton_t automaton)
5439 int cycle, unit;
5440 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5442 for (cycle = 0; cycle < max_cycles_num; cycle++)
5443 for (unit = 0; unit < description->units_num; unit++)
5444 if (units_array [unit]->automaton_decl
5445 == automaton->corresponding_automaton_decl
5446 && (cycle >= units_array [unit]->min_occ_cycle_num
5447 /* We can not remove queried unit from reservations. */
5448 || units_array [unit]->query_p
5449 /* We can not remove units which are used
5450 `exclusion_set', `presence_set',
5451 `final_presence_set', `absence_set', and
5452 `final_absence_set'. */
5453 || units_array [unit]->in_set_p))
5454 set_unit_reserv (reservs_matter, cycle, unit);
5455 return reservs_matter;
5458 /* The following function creates all states of nondeterministic AUTOMATON. */
5459 static void
5460 make_automaton (automaton_t automaton)
5462 ainsn_t ainsn;
5463 struct insn_reserv_decl *insn_reserv_decl;
5464 alt_state_t alt_state;
5465 state_t state;
5466 state_t start_state;
5467 state_t state2;
5468 ainsn_t advance_cycle_ainsn;
5469 arc_t added_arc;
5470 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5471 int states_n;
5472 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5474 /* Create the start state (empty state). */
5475 start_state = insert_state (get_free_state (1, automaton));
5476 automaton->start_state = start_state;
5477 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5478 VEC_safe_push (state_t, heap, state_stack, start_state);
5479 states_n = 1;
5480 while (VEC_length (state_t, state_stack) != 0)
5482 state = VEC_pop (state_t, state_stack);
5483 advance_cycle_ainsn = NULL;
5484 for (ainsn = automaton->ainsn_list;
5485 ainsn != NULL;
5486 ainsn = ainsn->next_ainsn)
5487 if (ainsn->first_insn_with_same_reservs)
5489 insn_reserv_decl = ainsn->insn_reserv_decl;
5490 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5492 /* We process alt_states in the same order as they are
5493 present in the description. */
5494 added_arc = NULL;
5495 for (alt_state = ainsn->alt_states;
5496 alt_state != NULL;
5497 alt_state = alt_state->next_alt_state)
5499 state2 = alt_state->state;
5500 if (!intersected_state_reservs_p (state, state2))
5502 state2 = states_union (state, state2, reservs_matter);
5503 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5505 state2->it_was_placed_in_stack_for_NDFA_forming
5506 = 1;
5507 VEC_safe_push (state_t, heap, state_stack, state2);
5508 states_n++;
5509 if (progress_flag && states_n % 100 == 0)
5510 fprintf (stderr, ".");
5512 added_arc = add_arc (state, state2, ainsn);
5513 if (!ndfa_flag)
5514 break;
5517 if (!ndfa_flag && added_arc != NULL)
5519 for (alt_state = ainsn->alt_states;
5520 alt_state != NULL;
5521 alt_state = alt_state->next_alt_state)
5522 state2 = alt_state->state;
5525 else
5526 advance_cycle_ainsn = ainsn;
5528 /* Add transition to advance cycle. */
5529 state2 = state_shift (state, reservs_matter);
5530 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5532 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5533 VEC_safe_push (state_t, heap, state_stack, state2);
5534 states_n++;
5535 if (progress_flag && states_n % 100 == 0)
5536 fprintf (stderr, ".");
5538 gcc_assert (advance_cycle_ainsn);
5539 add_arc (state, state2, advance_cycle_ainsn);
5541 VEC_free (state_t, heap, state_stack);
5544 /* Form lists of all arcs of STATE marked by the same ainsn. */
5545 static void
5546 form_arcs_marked_by_insn (state_t state)
5548 decl_t decl;
5549 arc_t arc;
5550 int i;
5552 for (i = 0; i < description->decls_num; i++)
5554 decl = description->decls [i];
5555 if (decl->mode == dm_insn_reserv)
5556 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5558 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5560 gcc_assert (arc->insn);
5561 arc->next_arc_marked_by_insn
5562 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5563 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5567 /* The function creates composed state (see comments for IR) from
5568 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5569 same insn. If the composed state is not in STATE_STACK yet, it is
5570 pushed into STATE_STACK. */
5572 static int
5573 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5574 VEC(state_t, heap) **state_stack)
5576 state_t state;
5577 alt_state_t alt_state, curr_alt_state;
5578 alt_state_t new_alt_state;
5579 arc_t curr_arc;
5580 arc_t next_arc;
5581 state_t state_in_table;
5582 state_t temp_state;
5583 alt_state_t canonical_alt_states_list;
5584 int alts_number;
5585 int new_state_p = 0;
5587 if (arcs_marked_by_insn == NULL)
5588 return new_state_p;
5589 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5590 state = arcs_marked_by_insn->to_state;
5591 else
5593 gcc_assert (ndfa_flag);
5594 /* Create composed state. */
5595 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5596 curr_alt_state = NULL;
5597 for (curr_arc = arcs_marked_by_insn;
5598 curr_arc != NULL;
5599 curr_arc = curr_arc->next_arc_marked_by_insn)
5600 if (curr_arc->to_state->component_states == NULL)
5602 new_alt_state = get_free_alt_state ();
5603 new_alt_state->next_alt_state = curr_alt_state;
5604 new_alt_state->state = curr_arc->to_state;
5605 curr_alt_state = new_alt_state;
5607 else
5608 for (alt_state = curr_arc->to_state->component_states;
5609 alt_state != NULL;
5610 alt_state = alt_state->next_sorted_alt_state)
5612 new_alt_state = get_free_alt_state ();
5613 new_alt_state->next_alt_state = curr_alt_state;
5614 new_alt_state->state = alt_state->state;
5615 gcc_assert (!alt_state->state->component_states);
5616 curr_alt_state = new_alt_state;
5618 /* There are not identical sets in the alt state list. */
5619 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5620 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5622 temp_state = state;
5623 state = canonical_alt_states_list->state;
5624 free_state (temp_state);
5626 else
5628 state->component_states = canonical_alt_states_list;
5629 state_in_table = insert_state (state);
5630 if (state_in_table != state)
5632 gcc_assert
5633 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5634 free_state (state);
5635 state = state_in_table;
5637 else
5639 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5640 new_state_p = 1;
5641 for (curr_alt_state = state->component_states;
5642 curr_alt_state != NULL;
5643 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5644 for (curr_arc = first_out_arc (curr_alt_state->state);
5645 curr_arc != NULL;
5646 curr_arc = next_out_arc (curr_arc))
5647 add_arc (state, curr_arc->to_state, curr_arc->insn);
5649 arcs_marked_by_insn->to_state = state;
5650 for (alts_number = 0,
5651 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5652 curr_arc != NULL;
5653 curr_arc = next_arc)
5655 next_arc = curr_arc->next_arc_marked_by_insn;
5656 remove_arc (original_state, curr_arc);
5657 alts_number++;
5661 if (!state->it_was_placed_in_stack_for_DFA_forming)
5663 state->it_was_placed_in_stack_for_DFA_forming = 1;
5664 VEC_safe_push (state_t, heap, *state_stack, state);
5666 return new_state_p;
5669 /* The function transforms nondeterministic AUTOMATON into
5670 deterministic. */
5672 static void
5673 NDFA_to_DFA (automaton_t automaton)
5675 state_t start_state;
5676 state_t state;
5677 decl_t decl;
5678 VEC(state_t, heap) *state_stack;
5679 int i;
5680 int states_n;
5682 state_stack = VEC_alloc (state_t, heap, 0);
5684 /* Create the start state (empty state). */
5685 start_state = automaton->start_state;
5686 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5687 VEC_safe_push (state_t, heap, state_stack, start_state);
5688 states_n = 1;
5689 while (VEC_length (state_t, state_stack) != 0)
5691 state = VEC_pop (state_t, state_stack);
5692 form_arcs_marked_by_insn (state);
5693 for (i = 0; i < description->decls_num; i++)
5695 decl = description->decls [i];
5696 if (decl->mode == dm_insn_reserv
5697 && create_composed_state
5698 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5699 &state_stack))
5701 states_n++;
5702 if (progress_flag && states_n % 100 == 0)
5703 fprintf (stderr, ".");
5707 VEC_free (state_t, heap, state_stack);
5710 /* The following variable value is current number (1, 2, ...) of passing
5711 graph of states. */
5712 static int curr_state_graph_pass_num;
5714 /* This recursive function passes all states achieved from START_STATE
5715 and applies APPLIED_FUNC to them. */
5716 static void
5717 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5719 arc_t arc;
5721 if (start_state->pass_num == curr_state_graph_pass_num)
5722 return;
5723 start_state->pass_num = curr_state_graph_pass_num;
5724 (*applied_func) (start_state);
5725 for (arc = first_out_arc (start_state);
5726 arc != NULL;
5727 arc = next_out_arc (arc))
5728 pass_state_graph (arc->to_state, applied_func);
5731 /* This recursive function passes all states of AUTOMATON and applies
5732 APPLIED_FUNC to them. */
5733 static void
5734 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5736 curr_state_graph_pass_num++;
5737 pass_state_graph (automaton->start_state, applied_func);
5740 /* The function initializes code for passing of all states. */
5741 static void
5742 initiate_pass_states (void)
5744 curr_state_graph_pass_num = 0;
5747 /* The following vla is used for storing pointers to all achieved
5748 states. */
5749 static VEC(state_t, heap) *all_achieved_states;
5751 /* This function is called by function pass_states to add an achieved
5752 STATE. */
5753 static void
5754 add_achieved_state (state_t state)
5756 VEC_safe_push (state_t, heap, all_achieved_states, state);
5759 /* The function sets up equivalence numbers of insns which mark all
5760 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5761 nonzero value) or by equiv_class_num_2 of the destination state.
5762 The function returns number of out arcs of STATE. */
5763 static void
5764 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5766 arc_t arc;
5768 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5770 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5771 arc->insn->insn_reserv_decl->equiv_class_num
5772 = (odd_iteration_flag
5773 ? arc->to_state->equiv_class_num_1
5774 : arc->to_state->equiv_class_num_2);
5775 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5779 /* The function clears equivalence numbers and alt_states in all insns
5780 which mark all out arcs of STATE. */
5781 static void
5782 clear_arc_insns_equiv_num (state_t state)
5784 arc_t arc;
5786 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5787 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5791 /* The following function returns TRUE if STATE reserves the unit with
5792 UNIT_NUM on the first cycle. */
5793 static int
5794 first_cycle_unit_presence (state_t state, int unit_num)
5796 alt_state_t alt_state;
5798 if (state->component_states == NULL)
5799 return test_unit_reserv (state->reservs, 0, unit_num);
5800 else
5802 for (alt_state = state->component_states;
5803 alt_state != NULL;
5804 alt_state = alt_state->next_sorted_alt_state)
5805 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5806 return true;
5808 return false;
5811 /* This fills in the presence_signature[] member of STATE. */
5812 static void
5813 cache_presence (state_t state)
5815 int i, num = 0;
5816 unsigned int sz;
5817 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5818 / (sizeof (int) * CHAR_BIT);
5820 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5821 for (i = 0; i < description->units_num; i++)
5822 if (units_array [i]->query_p)
5824 int presence1_p = first_cycle_unit_presence (state, i);
5825 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5826 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5827 num++;
5831 /* The function returns nonzero value if STATE is not equivalent to
5832 ANOTHER_STATE from the same current partition on equivalence
5833 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5834 output arcs. Iteration of making equivalence partition is defined
5835 by ODD_ITERATION_FLAG. */
5836 static int
5837 state_is_differed (state_t state, state_t another_state,
5838 int odd_iteration_flag)
5840 arc_t arc;
5841 unsigned int sz, si;
5843 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5845 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5846 / (sizeof (int) * CHAR_BIT);
5848 for (si = 0; si < sz; si++)
5849 gcc_assert (state->presence_signature[si]
5850 == another_state->presence_signature[si]);
5852 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5854 if ((odd_iteration_flag
5855 ? arc->to_state->equiv_class_num_1
5856 : arc->to_state->equiv_class_num_2)
5857 != arc->insn->insn_reserv_decl->equiv_class_num)
5858 return 1;
5861 return 0;
5864 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5865 and return -1, 0 or 1. This function can be used as predicate for
5866 qsort(). It requires the member presence_signature[] of both
5867 states be filled. */
5868 static int
5869 compare_states_for_equiv (const void *state_ptr_1,
5870 const void *state_ptr_2)
5872 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5873 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5874 unsigned int sz, si;
5875 if (s1->num_out_arcs < s2->num_out_arcs)
5876 return -1;
5877 else if (s1->num_out_arcs > s2->num_out_arcs)
5878 return 1;
5880 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5881 / (sizeof (int) * CHAR_BIT);
5883 for (si = 0; si < sz; si++)
5884 if (s1->presence_signature[si] < s2->presence_signature[si])
5885 return -1;
5886 else if (s1->presence_signature[si] > s2->presence_signature[si])
5887 return 1;
5888 return 0;
5891 /* The function makes initial partition of STATES on equivalent
5892 classes and saves it into *CLASSES. This function requires the input
5893 to be sorted via compare_states_for_equiv(). */
5894 static int
5895 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
5897 size_t i;
5898 state_t prev = 0;
5899 int class_num = 1;
5901 *classes = VEC_alloc (state_t, heap, 150);
5902 for (i = 0; i < VEC_length (state_t, states); i++)
5904 state_t state = VEC_index (state_t, states, i);
5905 if (prev)
5907 if (compare_states_for_equiv (&prev, &state) != 0)
5909 VEC_safe_push (state_t, heap, *classes, prev);
5910 class_num++;
5911 prev = NULL;
5914 state->equiv_class_num_1 = class_num;
5915 state->next_equiv_class_state = prev;
5916 prev = state;
5918 if (prev)
5919 VEC_safe_push (state_t, heap, *classes, prev);
5920 return class_num;
5923 /* The function copies pointers to equivalent states from vla FROM
5924 into vla TO. */
5925 static void
5926 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
5928 VEC_free (state_t, heap, *to);
5929 *to = VEC_copy (state_t, heap, from);
5932 /* The function processes equivalence class given by its first state,
5933 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5934 are not equivalent states, the function partitions the class
5935 removing nonequivalent states and placing them in
5936 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5937 assigns it to the state equivalence number. If the class has been
5938 partitioned, the function returns nonzero value. */
5939 static int
5940 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5941 VEC(state_t, heap) **next_iteration_classes,
5942 int *new_equiv_class_num_ptr)
5944 state_t new_equiv_class;
5945 int partition_p;
5946 state_t curr_state;
5947 state_t prev_state;
5948 state_t next_state;
5950 partition_p = 0;
5952 while (first_state != NULL)
5954 new_equiv_class = NULL;
5955 if (first_state->next_equiv_class_state != NULL)
5957 /* There are more one states in the class equivalence. */
5958 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5959 for (prev_state = first_state,
5960 curr_state = first_state->next_equiv_class_state;
5961 curr_state != NULL;
5962 curr_state = next_state)
5964 next_state = curr_state->next_equiv_class_state;
5965 if (state_is_differed (curr_state, first_state,
5966 odd_iteration_flag))
5968 /* Remove curr state from the class equivalence. */
5969 prev_state->next_equiv_class_state = next_state;
5970 /* Add curr state to the new class equivalence. */
5971 curr_state->next_equiv_class_state = new_equiv_class;
5972 if (new_equiv_class == NULL)
5973 (*new_equiv_class_num_ptr)++;
5974 if (odd_iteration_flag)
5975 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5976 else
5977 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5978 new_equiv_class = curr_state;
5979 partition_p = 1;
5981 else
5982 prev_state = curr_state;
5984 clear_arc_insns_equiv_num (first_state);
5986 if (new_equiv_class != NULL)
5987 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
5988 first_state = new_equiv_class;
5990 return partition_p;
5993 /* The function finds equivalent states of AUTOMATON. */
5994 static void
5995 evaluate_equiv_classes (automaton_t automaton,
5996 VEC(state_t, heap) **equiv_classes)
5998 int new_equiv_class_num;
5999 int odd_iteration_flag;
6000 int finish_flag;
6001 VEC (state_t, heap) *next_iteration_classes;
6002 size_t i;
6004 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6005 pass_states (automaton, add_achieved_state);
6006 pass_states (automaton, cache_presence);
6007 qsort (VEC_address (state_t, all_achieved_states),
6008 VEC_length (state_t, all_achieved_states),
6009 sizeof (state_t), compare_states_for_equiv);
6011 odd_iteration_flag = 0;
6012 new_equiv_class_num = init_equiv_class (all_achieved_states,
6013 &next_iteration_classes);
6017 odd_iteration_flag = !odd_iteration_flag;
6018 finish_flag = 1;
6019 copy_equiv_class (equiv_classes, next_iteration_classes);
6021 /* Transfer equiv numbers for the next iteration. */
6022 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6023 if (odd_iteration_flag)
6024 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6025 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6026 else
6027 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6028 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6030 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6031 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6032 odd_iteration_flag,
6033 &next_iteration_classes,
6034 &new_equiv_class_num))
6035 finish_flag = 0;
6037 while (!finish_flag);
6038 VEC_free (state_t, heap, next_iteration_classes);
6039 VEC_free (state_t, heap, all_achieved_states);
6042 /* The function merges equivalent states of AUTOMATON. */
6043 static void
6044 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6046 state_t curr_state;
6047 state_t new_state;
6048 state_t first_class_state;
6049 alt_state_t alt_states;
6050 alt_state_t alt_state, new_alt_state;
6051 arc_t curr_arc;
6052 arc_t next_arc;
6053 size_t i;
6055 /* Create states corresponding to equivalence classes containing two
6056 or more states. */
6057 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6059 curr_state = VEC_index (state_t, equiv_classes, i);
6060 if (curr_state->next_equiv_class_state != NULL)
6062 /* There are more one states in the class equivalence. */
6063 /* Create new compound state. */
6064 new_state = get_free_state (0, automaton);
6065 alt_states = NULL;
6066 first_class_state = curr_state;
6067 for (curr_state = first_class_state;
6068 curr_state != NULL;
6069 curr_state = curr_state->next_equiv_class_state)
6071 curr_state->equiv_class_state = new_state;
6072 if (curr_state->component_states == NULL)
6074 new_alt_state = get_free_alt_state ();
6075 new_alt_state->state = curr_state;
6076 new_alt_state->next_alt_state = alt_states;
6077 alt_states = new_alt_state;
6079 else
6080 for (alt_state = curr_state->component_states;
6081 alt_state != NULL;
6082 alt_state = alt_state->next_sorted_alt_state)
6084 new_alt_state = get_free_alt_state ();
6085 new_alt_state->state = alt_state->state;
6086 new_alt_state->next_alt_state = alt_states;
6087 alt_states = new_alt_state;
6090 /* Its is important that alt states were sorted before and
6091 after merging to have the same querying results. */
6092 new_state->component_states = uniq_sort_alt_states (alt_states);
6094 else
6095 curr_state->equiv_class_state = curr_state;
6098 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6100 curr_state = VEC_index (state_t, equiv_classes, i);
6101 if (curr_state->next_equiv_class_state != NULL)
6103 first_class_state = curr_state;
6104 /* Create new arcs output from the state corresponding to
6105 equiv class. */
6106 for (curr_arc = first_out_arc (first_class_state);
6107 curr_arc != NULL;
6108 curr_arc = next_out_arc (curr_arc))
6109 add_arc (first_class_state->equiv_class_state,
6110 curr_arc->to_state->equiv_class_state,
6111 curr_arc->insn);
6112 /* Delete output arcs from states of given class equivalence. */
6113 for (curr_state = first_class_state;
6114 curr_state != NULL;
6115 curr_state = curr_state->next_equiv_class_state)
6117 if (automaton->start_state == curr_state)
6118 automaton->start_state = curr_state->equiv_class_state;
6119 /* Delete the state and its output arcs. */
6120 for (curr_arc = first_out_arc (curr_state);
6121 curr_arc != NULL;
6122 curr_arc = next_arc)
6124 next_arc = next_out_arc (curr_arc);
6125 free_arc (curr_arc);
6129 else
6131 /* Change `to_state' of arcs output from the state of given
6132 equivalence class. */
6133 for (curr_arc = first_out_arc (curr_state);
6134 curr_arc != NULL;
6135 curr_arc = next_out_arc (curr_arc))
6136 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6141 /* The function sets up new_cycle_p for states if there is arc to the
6142 state marked by advance_cycle_insn_decl. */
6143 static void
6144 set_new_cycle_flags (state_t state)
6146 arc_t arc;
6148 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6149 if (arc->insn->insn_reserv_decl
6150 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6151 arc->to_state->new_cycle_p = 1;
6154 /* The top level function for minimization of deterministic
6155 AUTOMATON. */
6156 static void
6157 minimize_DFA (automaton_t automaton)
6159 VEC(state_t, heap) *equiv_classes = 0;
6161 evaluate_equiv_classes (automaton, &equiv_classes);
6162 merge_states (automaton, equiv_classes);
6163 pass_states (automaton, set_new_cycle_flags);
6165 VEC_free (state_t, heap, equiv_classes);
6168 /* Values of two variables are counted number of states and arcs in an
6169 automaton. */
6170 static int curr_counted_states_num;
6171 static int curr_counted_arcs_num;
6173 /* The function is called by function `pass_states' to count states
6174 and arcs of an automaton. */
6175 static void
6176 incr_states_and_arcs_nums (state_t state)
6178 arc_t arc;
6180 curr_counted_states_num++;
6181 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6182 curr_counted_arcs_num++;
6185 /* The function counts states and arcs of AUTOMATON. */
6186 static void
6187 count_states_and_arcs (automaton_t automaton, int *states_num,
6188 int *arcs_num)
6190 curr_counted_states_num = 0;
6191 curr_counted_arcs_num = 0;
6192 pass_states (automaton, incr_states_and_arcs_nums);
6193 *states_num = curr_counted_states_num;
6194 *arcs_num = curr_counted_arcs_num;
6197 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6198 recognition after checking and simplifying IR of the
6199 description. */
6200 static void
6201 build_automaton (automaton_t automaton)
6203 int states_num;
6204 int arcs_num;
6206 ticker_on (&NDFA_time);
6207 if (progress_flag)
6209 if (automaton->corresponding_automaton_decl == NULL)
6210 fprintf (stderr, "Create anonymous automaton");
6211 else
6212 fprintf (stderr, "Create automaton `%s'",
6213 automaton->corresponding_automaton_decl->name);
6214 fprintf (stderr, " (1 dot is 100 new states):");
6216 make_automaton (automaton);
6217 if (progress_flag)
6218 fprintf (stderr, " done\n");
6219 ticker_off (&NDFA_time);
6220 count_states_and_arcs (automaton, &states_num, &arcs_num);
6221 automaton->NDFA_states_num = states_num;
6222 automaton->NDFA_arcs_num = arcs_num;
6223 ticker_on (&NDFA_to_DFA_time);
6224 if (progress_flag)
6226 if (automaton->corresponding_automaton_decl == NULL)
6227 fprintf (stderr, "Make anonymous DFA");
6228 else
6229 fprintf (stderr, "Make DFA `%s'",
6230 automaton->corresponding_automaton_decl->name);
6231 fprintf (stderr, " (1 dot is 100 new states):");
6233 NDFA_to_DFA (automaton);
6234 if (progress_flag)
6235 fprintf (stderr, " done\n");
6236 ticker_off (&NDFA_to_DFA_time);
6237 count_states_and_arcs (automaton, &states_num, &arcs_num);
6238 automaton->DFA_states_num = states_num;
6239 automaton->DFA_arcs_num = arcs_num;
6240 if (!no_minimization_flag)
6242 ticker_on (&minimize_time);
6243 if (progress_flag)
6245 if (automaton->corresponding_automaton_decl == NULL)
6246 fprintf (stderr, "Minimize anonymous DFA...");
6247 else
6248 fprintf (stderr, "Minimize DFA `%s'...",
6249 automaton->corresponding_automaton_decl->name);
6251 minimize_DFA (automaton);
6252 if (progress_flag)
6253 fprintf (stderr, "done\n");
6254 ticker_off (&minimize_time);
6255 count_states_and_arcs (automaton, &states_num, &arcs_num);
6256 automaton->minimal_DFA_states_num = states_num;
6257 automaton->minimal_DFA_arcs_num = arcs_num;
6263 /* The page contains code for enumeration of all states of an automaton. */
6265 /* Variable used for enumeration of all states of an automaton. Its
6266 value is current number of automaton states. */
6267 static int curr_state_order_num;
6269 /* The function is called by function `pass_states' for enumerating
6270 states. */
6271 static void
6272 set_order_state_num (state_t state)
6274 state->order_state_num = curr_state_order_num;
6275 curr_state_order_num++;
6278 /* The function enumerates all states of AUTOMATON. */
6279 static void
6280 enumerate_states (automaton_t automaton)
6282 curr_state_order_num = 0;
6283 pass_states (automaton, set_order_state_num);
6284 automaton->achieved_states_num = curr_state_order_num;
6289 /* The page contains code for finding equivalent automaton insns
6290 (ainsns). */
6292 /* The function inserts AINSN into cyclic list
6293 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6294 static ainsn_t
6295 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6296 ainsn_t cyclic_equiv_class_insn_list)
6298 if (cyclic_equiv_class_insn_list == NULL)
6299 ainsn->next_equiv_class_insn = ainsn;
6300 else
6302 ainsn->next_equiv_class_insn
6303 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6304 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6306 return ainsn;
6309 /* The function deletes equiv_class_insn into cyclic list of
6310 equivalent ainsns. */
6311 static void
6312 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6314 ainsn_t curr_equiv_class_insn;
6315 ainsn_t prev_equiv_class_insn;
6317 prev_equiv_class_insn = equiv_class_insn;
6318 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6319 curr_equiv_class_insn != equiv_class_insn;
6320 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6321 prev_equiv_class_insn = curr_equiv_class_insn;
6322 if (prev_equiv_class_insn != equiv_class_insn)
6323 prev_equiv_class_insn->next_equiv_class_insn
6324 = equiv_class_insn->next_equiv_class_insn;
6327 /* The function processes AINSN of a state in order to find equivalent
6328 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6329 state. */
6330 static void
6331 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6333 ainsn_t next_insn;
6334 ainsn_t curr_insn;
6335 ainsn_t cyclic_insn_list;
6336 arc_t arc;
6338 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6339 curr_insn = ainsn;
6340 /* New class of ainsns which are not equivalent to given ainsn. */
6341 cyclic_insn_list = NULL;
6344 next_insn = curr_insn->next_equiv_class_insn;
6345 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6346 if (arc == NULL
6347 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6348 != arc->to_state))
6350 delete_ainsn_from_equiv_class (curr_insn);
6351 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6352 cyclic_insn_list);
6354 curr_insn = next_insn;
6356 while (curr_insn != ainsn);
6359 /* The function processes STATE in order to find equivalent ainsns. */
6360 static void
6361 process_state_for_insn_equiv_partition (state_t state)
6363 arc_t arc;
6364 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6366 /* Process insns of the arcs. */
6367 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6368 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6369 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6370 process_insn_equiv_class (arc->insn, insn_arcs_array);
6372 free (insn_arcs_array);
6375 /* The function searches for equivalent ainsns of AUTOMATON. */
6376 static void
6377 set_insn_equiv_classes (automaton_t automaton)
6379 ainsn_t ainsn;
6380 ainsn_t first_insn;
6381 ainsn_t curr_insn;
6382 ainsn_t cyclic_insn_list;
6383 ainsn_t insn_with_same_reservs;
6384 int equiv_classes_num;
6386 /* All insns are included in one equivalence class. */
6387 cyclic_insn_list = NULL;
6388 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6389 if (ainsn->first_insn_with_same_reservs)
6390 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6391 cyclic_insn_list);
6392 /* Process insns in order to make equivalence partition. */
6393 pass_states (automaton, process_state_for_insn_equiv_partition);
6394 /* Enumerate equiv classes. */
6395 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6396 /* Set undefined value. */
6397 ainsn->insn_equiv_class_num = -1;
6398 equiv_classes_num = 0;
6399 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6400 if (ainsn->insn_equiv_class_num < 0)
6402 first_insn = ainsn;
6403 gcc_assert (first_insn->first_insn_with_same_reservs);
6404 first_insn->first_ainsn_with_given_equivalence_num = 1;
6405 curr_insn = first_insn;
6408 for (insn_with_same_reservs = curr_insn;
6409 insn_with_same_reservs != NULL;
6410 insn_with_same_reservs
6411 = insn_with_same_reservs->next_same_reservs_insn)
6412 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6413 curr_insn = curr_insn->next_equiv_class_insn;
6415 while (curr_insn != first_insn);
6416 equiv_classes_num++;
6418 automaton->insn_equiv_classes_num = equiv_classes_num;
6423 /* This page contains code for creating DFA(s) and calls functions
6424 building them. */
6427 /* The following value is used to prevent floating point overflow for
6428 estimating an automaton bound. The value should be less DBL_MAX on
6429 the host machine. We use here approximate minimum of maximal
6430 double floating point value required by ANSI C standard. It
6431 will work for non ANSI sun compiler too. */
6433 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6435 /* The function estimate size of the single DFA used by PHR (pipeline
6436 hazards recognizer). */
6437 static double
6438 estimate_one_automaton_bound (void)
6440 decl_t decl;
6441 double one_automaton_estimation_bound;
6442 double root_value;
6443 int i;
6445 one_automaton_estimation_bound = 1.0;
6446 for (i = 0; i < description->decls_num; i++)
6448 decl = description->decls [i];
6449 if (decl->mode == dm_unit)
6451 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6452 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6453 / automata_num);
6454 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6455 > one_automaton_estimation_bound)
6456 one_automaton_estimation_bound *= root_value;
6459 return one_automaton_estimation_bound;
6462 /* The function compares unit declarations according to their maximal
6463 cycle in reservations. */
6464 static int
6465 compare_max_occ_cycle_nums (const void *unit_decl_1,
6466 const void *unit_decl_2)
6468 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6469 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6470 return 1;
6471 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6472 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6473 return 0;
6474 else
6475 return -1;
6478 /* The function makes heuristic assigning automata to units. Actually
6479 efficacy of the algorithm has been checked yet??? */
6481 static void
6482 units_to_automata_heuristic_distr (void)
6484 double estimation_bound;
6485 int automaton_num;
6486 int rest_units_num;
6487 double bound_value;
6488 unit_decl_t *unit_decls;
6489 int i, j;
6491 if (description->units_num == 0)
6492 return;
6493 estimation_bound = estimate_one_automaton_bound ();
6494 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6496 for (i = 0, j = 0; i < description->decls_num; i++)
6497 if (description->decls[i]->mode == dm_unit)
6498 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6499 gcc_assert (j == description->units_num);
6501 qsort (unit_decls, description->units_num,
6502 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6504 automaton_num = 0;
6505 bound_value = unit_decls[0]->max_occ_cycle_num;
6506 unit_decls[0]->corresponding_automaton_num = automaton_num;
6508 for (i = 1; i < description->units_num; i++)
6510 rest_units_num = description->units_num - i + 1;
6511 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6512 if (automaton_num < automata_num - 1
6513 && ((automata_num - automaton_num - 1 == rest_units_num)
6514 || (bound_value
6515 > (estimation_bound
6516 / unit_decls[i]->max_occ_cycle_num))))
6518 bound_value = unit_decls[i]->max_occ_cycle_num;
6519 automaton_num++;
6521 else
6522 bound_value *= unit_decls[i]->max_occ_cycle_num;
6523 unit_decls[i]->corresponding_automaton_num = automaton_num;
6525 gcc_assert (automaton_num == automata_num - 1);
6526 free (unit_decls);
6529 /* The functions creates automaton insns for each automata. Automaton
6530 insn is simply insn for given automaton which makes reservation
6531 only of units of the automaton. */
6532 static ainsn_t
6533 create_ainsns (void)
6535 decl_t decl;
6536 ainsn_t first_ainsn;
6537 ainsn_t curr_ainsn;
6538 ainsn_t prev_ainsn;
6539 int i;
6541 first_ainsn = NULL;
6542 prev_ainsn = NULL;
6543 for (i = 0; i < description->decls_num; i++)
6545 decl = description->decls [i];
6546 if (decl->mode == dm_insn_reserv)
6548 curr_ainsn = XCREATENODE (struct ainsn);
6549 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6550 curr_ainsn->important_p = FALSE;
6551 curr_ainsn->next_ainsn = NULL;
6552 if (prev_ainsn == NULL)
6553 first_ainsn = curr_ainsn;
6554 else
6555 prev_ainsn->next_ainsn = curr_ainsn;
6556 prev_ainsn = curr_ainsn;
6559 return first_ainsn;
6562 /* The function assigns automata to units according to constructions
6563 `define_automaton' in the description. */
6564 static void
6565 units_to_automata_distr (void)
6567 decl_t decl;
6568 int i;
6570 for (i = 0; i < description->decls_num; i++)
6572 decl = description->decls [i];
6573 if (decl->mode == dm_unit)
6575 if (DECL_UNIT (decl)->automaton_decl == NULL
6576 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6577 == NULL))
6578 /* Distribute to the first automaton. */
6579 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6580 else
6581 DECL_UNIT (decl)->corresponding_automaton_num
6582 = (DECL_UNIT (decl)->automaton_decl
6583 ->corresponding_automaton->automaton_order_num);
6588 /* The function creates DFA(s) for fast pipeline hazards recognition
6589 after checking and simplifying IR of the description. */
6590 static void
6591 create_automata (void)
6593 automaton_t curr_automaton;
6594 automaton_t prev_automaton;
6595 decl_t decl;
6596 int curr_automaton_num;
6597 int i;
6599 if (automata_num != 0)
6601 units_to_automata_heuristic_distr ();
6602 for (prev_automaton = NULL, curr_automaton_num = 0;
6603 curr_automaton_num < automata_num;
6604 curr_automaton_num++, prev_automaton = curr_automaton)
6606 curr_automaton = XCREATENODE (struct automaton);
6607 curr_automaton->ainsn_list = create_ainsns ();
6608 curr_automaton->corresponding_automaton_decl = NULL;
6609 curr_automaton->next_automaton = NULL;
6610 curr_automaton->automaton_order_num = curr_automaton_num;
6611 if (prev_automaton == NULL)
6612 description->first_automaton = curr_automaton;
6613 else
6614 prev_automaton->next_automaton = curr_automaton;
6617 else
6619 curr_automaton_num = 0;
6620 prev_automaton = NULL;
6621 for (i = 0; i < description->decls_num; i++)
6623 decl = description->decls [i];
6624 if (decl->mode == dm_automaton
6625 && DECL_AUTOMATON (decl)->automaton_is_used)
6627 curr_automaton = XCREATENODE (struct automaton);
6628 curr_automaton->ainsn_list = create_ainsns ();
6629 curr_automaton->corresponding_automaton_decl
6630 = DECL_AUTOMATON (decl);
6631 curr_automaton->next_automaton = NULL;
6632 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6633 curr_automaton->automaton_order_num = curr_automaton_num;
6634 if (prev_automaton == NULL)
6635 description->first_automaton = curr_automaton;
6636 else
6637 prev_automaton->next_automaton = curr_automaton;
6638 curr_automaton_num++;
6639 prev_automaton = curr_automaton;
6642 if (curr_automaton_num == 0)
6644 curr_automaton = XCREATENODE (struct automaton);
6645 curr_automaton->ainsn_list = create_ainsns ();
6646 curr_automaton->corresponding_automaton_decl = NULL;
6647 curr_automaton->next_automaton = NULL;
6648 description->first_automaton = curr_automaton;
6650 units_to_automata_distr ();
6652 NDFA_time = create_ticker ();
6653 ticker_off (&NDFA_time);
6654 NDFA_to_DFA_time = create_ticker ();
6655 ticker_off (&NDFA_to_DFA_time);
6656 minimize_time = create_ticker ();
6657 ticker_off (&minimize_time);
6658 equiv_time = create_ticker ();
6659 ticker_off (&equiv_time);
6660 for (curr_automaton = description->first_automaton;
6661 curr_automaton != NULL;
6662 curr_automaton = curr_automaton->next_automaton)
6664 if (progress_flag)
6666 if (curr_automaton->corresponding_automaton_decl == NULL)
6667 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6668 else
6669 fprintf (stderr, "Prepare automaton `%s' creation...",
6670 curr_automaton->corresponding_automaton_decl->name);
6672 create_alt_states (curr_automaton);
6673 form_ainsn_with_same_reservs (curr_automaton);
6674 if (progress_flag)
6675 fprintf (stderr, "done\n");
6676 build_automaton (curr_automaton);
6677 enumerate_states (curr_automaton);
6678 ticker_on (&equiv_time);
6679 set_insn_equiv_classes (curr_automaton);
6680 ticker_off (&equiv_time);
6686 /* This page contains code for forming string representation of
6687 regexp. The representation is formed on IR obstack. So you should
6688 not work with IR obstack between regexp_representation and
6689 finish_regexp_representation calls. */
6691 /* This recursive function forms string representation of regexp
6692 (without tailing '\0'). */
6693 static void
6694 form_regexp (regexp_t regexp)
6696 int i;
6698 switch (regexp->mode)
6700 case rm_unit: case rm_reserv:
6702 const char *name = (regexp->mode == rm_unit
6703 ? REGEXP_UNIT (regexp)->name
6704 : REGEXP_RESERV (regexp)->name);
6706 obstack_grow (&irp, name, strlen (name));
6707 break;
6710 case rm_sequence:
6711 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6713 if (i != 0)
6714 obstack_1grow (&irp, ',');
6715 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6717 break;
6719 case rm_allof:
6720 obstack_1grow (&irp, '(');
6721 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6723 if (i != 0)
6724 obstack_1grow (&irp, '+');
6725 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6726 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6727 obstack_1grow (&irp, '(');
6728 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6729 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6730 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6731 obstack_1grow (&irp, ')');
6733 obstack_1grow (&irp, ')');
6734 break;
6736 case rm_oneof:
6737 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6739 if (i != 0)
6740 obstack_1grow (&irp, '|');
6741 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6742 obstack_1grow (&irp, '(');
6743 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6744 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6745 obstack_1grow (&irp, ')');
6747 break;
6749 case rm_repeat:
6751 char digits [30];
6753 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6754 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6755 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6756 obstack_1grow (&irp, '(');
6757 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6758 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6759 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6760 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6761 obstack_1grow (&irp, ')');
6762 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6763 obstack_grow (&irp, digits, strlen (digits));
6764 break;
6767 case rm_nothing:
6768 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6769 break;
6771 default:
6772 gcc_unreachable ();
6776 /* The function returns string representation of REGEXP on IR
6777 obstack. */
6778 static const char *
6779 regexp_representation (regexp_t regexp)
6781 form_regexp (regexp);
6782 obstack_1grow (&irp, '\0');
6783 return obstack_base (&irp);
6786 /* The function frees memory allocated for last formed string
6787 representation of regexp. */
6788 static void
6789 finish_regexp_representation (void)
6791 int length = obstack_object_size (&irp);
6793 obstack_blank_fast (&irp, -length);
6798 /* This page contains code for output PHR (pipeline hazards recognizer). */
6800 /* The function outputs minimal C type which is sufficient for
6801 representation numbers in range min_range_value and
6802 max_range_value. Because host machine and build machine may be
6803 different, we use here minimal values required by ANSI C standard
6804 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6805 approximation. */
6807 static void
6808 output_range_type (FILE *f, long int min_range_value,
6809 long int max_range_value)
6811 if (min_range_value >= 0 && max_range_value <= 255)
6812 fprintf (f, "unsigned char");
6813 else if (min_range_value >= -127 && max_range_value <= 127)
6814 fprintf (f, "signed char");
6815 else if (min_range_value >= 0 && max_range_value <= 65535)
6816 fprintf (f, "unsigned short");
6817 else if (min_range_value >= -32767 && max_range_value <= 32767)
6818 fprintf (f, "short");
6819 else
6820 fprintf (f, "int");
6823 /* The function outputs all initialization values of VECT. */
6824 static void
6825 output_vect (vla_hwint_t vect)
6827 int els_on_line;
6828 size_t vect_length = VEC_length (vect_el_t, vect);
6829 size_t i;
6831 els_on_line = 1;
6832 if (vect_length == 0)
6833 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6834 else
6835 for (i = 0; i < vect_length; i++)
6837 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6838 if (els_on_line == 10)
6840 els_on_line = 0;
6841 fputs (",\n", output_file);
6843 else if (i < vect_length-1)
6844 fputs (", ", output_file);
6845 els_on_line++;
6849 /* The following is name of the structure which represents DFA(s) for
6850 PHR. */
6851 #define CHIP_NAME "DFA_chip"
6853 /* The following is name of member which represents state of a DFA for
6854 PHR. */
6855 static void
6856 output_chip_member_name (FILE *f, automaton_t automaton)
6858 if (automaton->corresponding_automaton_decl == NULL)
6859 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6860 else
6861 fprintf (f, "%s_automaton_state",
6862 automaton->corresponding_automaton_decl->name);
6865 /* The following is name of temporary variable which stores state of a
6866 DFA for PHR. */
6867 static void
6868 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6870 fprintf (f, "_");
6871 output_chip_member_name (f, automaton);
6874 /* This is name of macro value which is code of pseudo_insn
6875 representing advancing cpu cycle. Its value is used as internal
6876 code unknown insn. */
6877 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6879 /* Output name of translate vector for given automaton. */
6880 static void
6881 output_translate_vect_name (FILE *f, automaton_t automaton)
6883 if (automaton->corresponding_automaton_decl == NULL)
6884 fprintf (f, "translate_%d", automaton->automaton_order_num);
6885 else
6886 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6889 /* Output name for simple transition table representation. */
6890 static void
6891 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6893 if (automaton->corresponding_automaton_decl == NULL)
6894 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6895 else
6896 fprintf (f, "%s_transitions",
6897 automaton->corresponding_automaton_decl->name);
6900 /* Output name of comb vector of the transition table for given
6901 automaton. */
6902 static void
6903 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6905 if (automaton->corresponding_automaton_decl == NULL)
6906 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6907 else
6908 fprintf (f, "%s_transitions",
6909 automaton->corresponding_automaton_decl->name);
6912 /* Output name of check vector of the transition table for given
6913 automaton. */
6914 static void
6915 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6917 if (automaton->corresponding_automaton_decl == NULL)
6918 fprintf (f, "check_%d", automaton->automaton_order_num);
6919 else
6920 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6923 /* Output name of base vector of the transition table for given
6924 automaton. */
6925 static void
6926 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6928 if (automaton->corresponding_automaton_decl == NULL)
6929 fprintf (f, "base_%d", automaton->automaton_order_num);
6930 else
6931 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6934 /* Output name of simple min issue delay table representation. */
6935 static void
6936 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6938 if (automaton->corresponding_automaton_decl == NULL)
6939 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6940 else
6941 fprintf (f, "%s_min_issue_delay",
6942 automaton->corresponding_automaton_decl->name);
6945 /* Output name of deadlock vector for given automaton. */
6946 static void
6947 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6949 if (automaton->corresponding_automaton_decl == NULL)
6950 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6951 else
6952 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6955 /* Output name of reserved units table for AUTOMATON into file F. */
6956 static void
6957 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6959 if (automaton->corresponding_automaton_decl == NULL)
6960 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6961 else
6962 fprintf (f, "%s_reserved_units",
6963 automaton->corresponding_automaton_decl->name);
6966 /* Name of the PHR interface macro. */
6967 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6969 /* Names of an internal functions: */
6970 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6972 /* This is external type of DFA(s) state. */
6973 #define STATE_TYPE_NAME "state_t"
6975 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6977 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6979 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6981 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6983 /* Name of cache of insn dfa codes. */
6984 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6986 /* Name of length of cache of insn dfa codes. */
6987 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6989 /* Names of the PHR interface functions: */
6990 #define SIZE_FUNC_NAME "state_size"
6992 #define TRANSITION_FUNC_NAME "state_transition"
6994 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6996 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6998 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7000 #define RESET_FUNC_NAME "state_reset"
7002 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7004 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7006 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7008 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7010 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7012 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7014 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7016 #define DFA_START_FUNC_NAME "dfa_start"
7018 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7020 /* Names of parameters of the PHR interface functions. */
7021 #define STATE_NAME "state"
7023 #define INSN_PARAMETER_NAME "insn"
7025 #define INSN2_PARAMETER_NAME "insn2"
7027 #define CHIP_PARAMETER_NAME "chip"
7029 #define FILE_PARAMETER_NAME "f"
7031 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7033 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7035 /* Names of the variables whose values are internal insn code of rtx
7036 insn. */
7037 #define INTERNAL_INSN_CODE_NAME "insn_code"
7039 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7041 /* Names of temporary variables in some functions. */
7042 #define TEMPORARY_VARIABLE_NAME "temp"
7044 #define I_VARIABLE_NAME "i"
7046 /* Name of result variable in some functions. */
7047 #define RESULT_VARIABLE_NAME "res"
7049 /* Name of function (attribute) to translate insn into internal insn
7050 code. */
7051 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7053 /* Name of function (attribute) to translate insn into internal insn
7054 code with caching. */
7055 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7057 /* Output C type which is used for representation of codes of states
7058 of AUTOMATON. */
7059 static void
7060 output_state_member_type (FILE *f, automaton_t automaton)
7062 output_range_type (f, 0, automaton->achieved_states_num);
7065 /* Output definition of the structure representing current DFA(s)
7066 state(s). */
7067 static void
7068 output_chip_definitions (void)
7070 automaton_t automaton;
7072 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7073 for (automaton = description->first_automaton;
7074 automaton != NULL;
7075 automaton = automaton->next_automaton)
7077 fprintf (output_file, " ");
7078 output_state_member_type (output_file, automaton);
7079 fprintf (output_file, " ");
7080 output_chip_member_name (output_file, automaton);
7081 fprintf (output_file, ";\n");
7083 fprintf (output_file, "};\n\n");
7084 #if 0
7085 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7086 #endif
7090 /* The function outputs translate vector of internal insn code into
7091 insn equivalence class number. The equivalence class number is
7092 used to access to table and vectors representing DFA(s). */
7093 static void
7094 output_translate_vect (automaton_t automaton)
7096 ainsn_t ainsn;
7097 int insn_value;
7098 vla_hwint_t translate_vect;
7100 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7102 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7103 /* Undefined value */
7104 VEC_quick_push (vect_el_t, translate_vect,
7105 automaton->insn_equiv_classes_num);
7107 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7108 VEC_replace (vect_el_t, translate_vect,
7109 ainsn->insn_reserv_decl->insn_num,
7110 ainsn->insn_equiv_class_num);
7112 fprintf (output_file,
7113 "/* Vector translating external insn codes to internal ones.*/\n");
7114 fprintf (output_file, "static const ");
7115 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7116 fprintf (output_file, " ");
7117 output_translate_vect_name (output_file, automaton);
7118 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7119 output_vect (translate_vect);
7120 fprintf (output_file, "};\n\n");
7121 VEC_free (vect_el_t, heap, translate_vect);
7124 /* The value in a table state x ainsn -> something which represents
7125 undefined value. */
7126 static int undefined_vect_el_value;
7128 /* The following function returns nonzero value if the best
7129 representation of the table is comb vector. */
7130 static int
7131 comb_vect_p (state_ainsn_table_t tab)
7133 return (2 * VEC_length (vect_el_t, tab->full_vect)
7134 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7137 /* The following function creates new table for AUTOMATON. */
7138 static state_ainsn_table_t
7139 create_state_ainsn_table (automaton_t automaton)
7141 state_ainsn_table_t tab;
7142 int full_vect_length;
7143 int i;
7145 tab = XCREATENODE (struct state_ainsn_table);
7146 tab->automaton = automaton;
7148 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7149 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7151 tab->base_vect = 0;
7152 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7153 automaton->achieved_states_num);
7155 full_vect_length = (automaton->insn_equiv_classes_num
7156 * automaton->achieved_states_num);
7157 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7158 for (i = 0; i < full_vect_length; i++)
7159 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7161 tab->min_base_vect_el_value = 0;
7162 tab->max_base_vect_el_value = 0;
7163 tab->min_comb_vect_el_value = 0;
7164 tab->max_comb_vect_el_value = 0;
7165 return tab;
7168 /* The following function outputs the best C representation of the
7169 table TAB of given TABLE_NAME. */
7170 static void
7171 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7172 void (*output_full_vect_name_func) (FILE *, automaton_t),
7173 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7174 void (*output_check_vect_name_func) (FILE *, automaton_t),
7175 void (*output_base_vect_name_func) (FILE *, automaton_t))
7177 if (!comb_vect_p (tab))
7179 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7180 fprintf (output_file, "static const ");
7181 output_range_type (output_file, tab->min_comb_vect_el_value,
7182 tab->max_comb_vect_el_value);
7183 fprintf (output_file, " ");
7184 (*output_full_vect_name_func) (output_file, tab->automaton);
7185 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7186 output_vect (tab->full_vect);
7187 fprintf (output_file, "};\n\n");
7189 else
7191 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7192 fprintf (output_file, "static const ");
7193 output_range_type (output_file, tab->min_comb_vect_el_value,
7194 tab->max_comb_vect_el_value);
7195 fprintf (output_file, " ");
7196 (*output_comb_vect_name_func) (output_file, tab->automaton);
7197 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7198 output_vect (tab->comb_vect);
7199 fprintf (output_file, "};\n\n");
7200 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7201 fprintf (output_file, "static const ");
7202 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7203 fprintf (output_file, " ");
7204 (*output_check_vect_name_func) (output_file, tab->automaton);
7205 fprintf (output_file, "[] = {\n");
7206 output_vect (tab->check_vect);
7207 fprintf (output_file, "};\n\n");
7208 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7209 fprintf (output_file, "static const ");
7210 output_range_type (output_file, tab->min_base_vect_el_value,
7211 tab->max_base_vect_el_value);
7212 fprintf (output_file, " ");
7213 (*output_base_vect_name_func) (output_file, tab->automaton);
7214 fprintf (output_file, "[] = {\n");
7215 output_vect (tab->base_vect);
7216 fprintf (output_file, "};\n\n");
7220 /* The following function adds vector VECT to table TAB as its line
7221 with number VECT_NUM. */
7222 static void
7223 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7225 int vect_length;
7226 size_t real_vect_length;
7227 int comb_vect_index;
7228 int comb_vect_els_num;
7229 int vect_index;
7230 int first_unempty_vect_index;
7231 int additional_els_num;
7232 int no_state_value;
7233 vect_el_t vect_el;
7234 int i;
7235 unsigned long vect_mask, comb_vect_mask;
7237 vect_length = VEC_length (vect_el_t, vect);
7238 gcc_assert (vect_length);
7239 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7240 real_vect_length = tab->automaton->insn_equiv_classes_num;
7241 /* Form full vector in the table: */
7243 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7244 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7245 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7246 full_base + vect_length);
7247 for (i = 0; i < vect_length; i++)
7248 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7249 VEC_index (vect_el_t, vect, i));
7251 /* Form comb vector in the table: */
7252 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7253 == VEC_length (vect_el_t, tab->check_vect));
7255 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7256 for (first_unempty_vect_index = 0;
7257 first_unempty_vect_index < vect_length;
7258 first_unempty_vect_index++)
7259 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7260 != undefined_vect_el_value)
7261 break;
7263 /* Search for the place in comb vect for the inserted vect. */
7265 /* Slow case. */
7266 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7268 for (comb_vect_index = 0;
7269 comb_vect_index < comb_vect_els_num;
7270 comb_vect_index++)
7272 for (vect_index = first_unempty_vect_index;
7273 vect_index < vect_length
7274 && vect_index + comb_vect_index < comb_vect_els_num;
7275 vect_index++)
7276 if (VEC_index (vect_el_t, vect, vect_index)
7277 != undefined_vect_el_value
7278 && (VEC_index (vect_el_t, tab->comb_vect,
7279 vect_index + comb_vect_index)
7280 != undefined_vect_el_value))
7281 break;
7282 if (vect_index >= vect_length
7283 || vect_index + comb_vect_index >= comb_vect_els_num)
7284 break;
7286 goto found;
7289 /* Fast case. */
7290 vect_mask = 0;
7291 for (vect_index = first_unempty_vect_index;
7292 vect_index < vect_length;
7293 vect_index++)
7295 vect_mask = vect_mask << 1;
7296 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7297 vect_mask |= 1;
7300 /* Search for the place in comb vect for the inserted vect. */
7301 comb_vect_index = 0;
7302 if (comb_vect_els_num == 0)
7303 goto found;
7305 comb_vect_mask = 0;
7306 for (vect_index = first_unempty_vect_index;
7307 vect_index < vect_length && vect_index < comb_vect_els_num;
7308 vect_index++)
7310 comb_vect_mask <<= 1;
7311 if (vect_index + comb_vect_index < comb_vect_els_num
7312 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7313 != undefined_vect_el_value)
7314 comb_vect_mask |= 1;
7316 if ((vect_mask & comb_vect_mask) == 0)
7317 goto found;
7319 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7320 comb_vect_index++, i++)
7322 comb_vect_mask = (comb_vect_mask << 1) | 1;
7323 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7324 == undefined_vect_el_value);
7325 if ((vect_mask & comb_vect_mask) == 0)
7326 goto found;
7328 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7330 comb_vect_mask <<= 1;
7331 if ((vect_mask & comb_vect_mask) == 0)
7332 goto found;
7335 found:
7336 /* Slot was found. */
7337 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7338 if (additional_els_num < 0)
7339 additional_els_num = 0;
7340 /* Expand comb and check vectors. */
7341 vect_el = undefined_vect_el_value;
7342 no_state_value = tab->automaton->achieved_states_num;
7343 while (additional_els_num > 0)
7345 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7346 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7347 additional_els_num--;
7349 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7350 >= comb_vect_index + real_vect_length);
7351 /* Fill comb and check vectors. */
7352 for (vect_index = 0; vect_index < vect_length; vect_index++)
7353 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7355 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7356 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7357 comb_vect_index + vect_index)
7358 == undefined_vect_el_value);
7359 gcc_assert (x >= 0);
7360 if (tab->max_comb_vect_el_value < x)
7361 tab->max_comb_vect_el_value = x;
7362 if (tab->min_comb_vect_el_value > x)
7363 tab->min_comb_vect_el_value = x;
7364 VEC_replace (vect_el_t, tab->comb_vect,
7365 comb_vect_index + vect_index, x);
7366 VEC_replace (vect_el_t, tab->check_vect,
7367 comb_vect_index + vect_index, vect_num);
7369 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7370 tab->max_comb_vect_el_value = undefined_vect_el_value;
7371 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7372 tab->min_comb_vect_el_value = undefined_vect_el_value;
7373 if (tab->max_base_vect_el_value < comb_vect_index)
7374 tab->max_base_vect_el_value = comb_vect_index;
7375 if (tab->min_base_vect_el_value > comb_vect_index)
7376 tab->min_base_vect_el_value = comb_vect_index;
7378 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7381 /* Return number of out arcs of STATE. */
7382 static int
7383 out_state_arcs_num (const_state_t state)
7385 int result;
7386 arc_t arc;
7388 result = 0;
7389 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7391 gcc_assert (arc->insn);
7392 if (arc->insn->first_ainsn_with_given_equivalence_num)
7393 result++;
7395 return result;
7398 /* Compare number of possible transitions from the states. */
7399 static int
7400 compare_transition_els_num (const void *state_ptr_1,
7401 const void *state_ptr_2)
7403 const int transition_els_num_1
7404 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7405 const int transition_els_num_2
7406 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7408 if (transition_els_num_1 < transition_els_num_2)
7409 return 1;
7410 else if (transition_els_num_1 == transition_els_num_2)
7411 return 0;
7412 else
7413 return -1;
7416 /* The function adds element EL_VALUE to vector VECT for a table state
7417 x AINSN. */
7418 static void
7419 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7421 int equiv_class_num;
7422 int vect_index;
7424 gcc_assert (ainsn);
7425 equiv_class_num = ainsn->insn_equiv_class_num;
7426 for (vect_index = VEC_length (vect_el_t, *vect);
7427 vect_index <= equiv_class_num;
7428 vect_index++)
7429 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7430 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7433 /* This is for forming vector of states of an automaton. */
7434 static VEC(state_t, heap) *output_states_vect;
7436 /* The function is called by function pass_states. The function adds
7437 STATE to `output_states_vect'. */
7438 static void
7439 add_states_vect_el (state_t state)
7441 VEC_safe_push (state_t, heap, output_states_vect, state);
7444 /* Form and output vectors (comb, check, base or full vector)
7445 representing transition table of AUTOMATON. */
7446 static void
7447 output_trans_table (automaton_t automaton)
7449 size_t i;
7450 arc_t arc;
7451 vla_hwint_t transition_vect = 0;
7453 undefined_vect_el_value = automaton->achieved_states_num;
7454 automaton->trans_table = create_state_ainsn_table (automaton);
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);
7459 qsort (VEC_address (state_t, output_states_vect),
7460 VEC_length (state_t, output_states_vect),
7461 sizeof (state_t), compare_transition_els_num);
7463 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7465 VEC_truncate (vect_el_t, transition_vect, 0);
7466 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7467 arc != NULL;
7468 arc = next_out_arc (arc))
7470 gcc_assert (arc->insn);
7471 if (arc->insn->first_ainsn_with_given_equivalence_num)
7472 add_vect_el (&transition_vect, arc->insn,
7473 arc->to_state->order_state_num);
7475 add_vect (automaton->trans_table,
7476 VEC_index (state_t, output_states_vect, i)->order_state_num,
7477 transition_vect);
7479 output_state_ainsn_table
7480 (automaton->trans_table, "state transitions",
7481 output_trans_full_vect_name, output_trans_comb_vect_name,
7482 output_trans_check_vect_name, output_trans_base_vect_name);
7484 VEC_free (state_t, heap, output_states_vect);
7485 VEC_free (vect_el_t, heap, transition_vect);
7488 /* Form and output vectors representing minimal issue delay table of
7489 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7490 the ainsn. */
7491 static void
7492 output_min_issue_delay_table (automaton_t automaton)
7494 vla_hwint_t min_issue_delay_vect;
7495 vla_hwint_t compressed_min_issue_delay_vect;
7496 ainsn_t ainsn;
7497 size_t i;
7498 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7499 size_t cfactor;
7500 int changed;
7502 /* Create vect of pointers to states ordered by num of transitions
7503 from the state (state with the maximum num is the first). */
7504 output_states_vect = 0;
7505 pass_states (automaton, add_states_vect_el);
7507 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7508 * automaton->insn_equiv_classes_num);
7509 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7510 for (i = 0; i < min_issue_delay_len; i++)
7511 VEC_quick_push (vect_el_t, min_issue_delay_vect, -1);
7513 automaton->max_min_delay = 0;
7517 size_t state_no;
7519 changed = 0;
7521 for (state_no = 0; state_no < VEC_length (state_t, output_states_vect);
7522 state_no++)
7524 state_t s = VEC_index (state_t, output_states_vect, state_no);
7525 arc_t arc;
7527 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7529 int k;
7531 size_t asn = s->order_state_num
7532 * automaton->insn_equiv_classes_num
7533 + arc->insn->insn_equiv_class_num;
7535 if (VEC_index (vect_el_t, min_issue_delay_vect, asn))
7537 VEC_replace (vect_el_t, min_issue_delay_vect, asn, 0);
7538 changed = 1;
7541 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7543 size_t n0, n1;
7544 vect_el_t delay0, delay1;
7546 n0 = s->order_state_num
7547 * automaton->insn_equiv_classes_num
7548 + k;
7549 n1 = arc->to_state->order_state_num
7550 * automaton->insn_equiv_classes_num
7551 + k;
7552 delay0 = VEC_index (vect_el_t, min_issue_delay_vect, n0);
7553 delay1 = VEC_index (vect_el_t, min_issue_delay_vect, n1);
7554 if (delay1 != -1)
7556 if (arc->insn->insn_reserv_decl
7557 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7558 delay1++;
7559 if (delay1 < delay0 || delay0 == -1)
7561 VEC_replace (vect_el_t, min_issue_delay_vect, n0, delay1);
7562 changed = 1;
7569 while (changed);
7571 automaton->max_min_delay = 0;
7573 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7574 if (ainsn->first_ainsn_with_given_equivalence_num)
7576 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7578 state_t s = VEC_index (state_t, output_states_vect, i);
7579 size_t np = s->order_state_num
7580 * automaton->insn_equiv_classes_num
7581 + ainsn->insn_equiv_class_num;
7582 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, np);
7584 if (automaton->max_min_delay < x)
7585 automaton->max_min_delay = x;
7586 if (x == -1)
7587 VEC_replace (vect_el_t, min_issue_delay_vect, np, 0);
7591 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7592 fprintf (output_file, "static const ");
7593 output_range_type (output_file, 0, automaton->max_min_delay);
7594 fprintf (output_file, " ");
7595 output_min_issue_delay_vect_name (output_file, automaton);
7596 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7597 /* Compress the vector. */
7598 if (automaton->max_min_delay < 2)
7599 cfactor = 8;
7600 else if (automaton->max_min_delay < 4)
7601 cfactor = 4;
7602 else if (automaton->max_min_delay < 16)
7603 cfactor = 2;
7604 else
7605 cfactor = 1;
7606 automaton->min_issue_delay_table_compression_factor = cfactor;
7608 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7609 compressed_min_issue_delay_vect
7610 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7612 for (i = 0; i < compressed_min_issue_delay_len; i++)
7613 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7615 for (i = 0; i < min_issue_delay_len; i++)
7617 size_t ci = i / cfactor;
7618 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7619 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7621 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7622 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7624 output_vect (compressed_min_issue_delay_vect);
7625 fprintf (output_file, "};\n\n");
7626 VEC_free (state_t, heap, output_states_vect);
7627 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7628 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7631 /* Form and output vector representing the locked states of
7632 AUTOMATON. */
7633 static void
7634 output_dead_lock_vect (automaton_t automaton)
7636 size_t i;
7637 arc_t arc;
7638 vla_hwint_t dead_lock_vect = 0;
7640 /* Create vect of pointers to states ordered by num of
7641 transitions from the state (state with the maximum num is the
7642 first). */
7643 automaton->locked_states = 0;
7644 output_states_vect = 0;
7645 pass_states (automaton, add_states_vect_el);
7647 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7648 VEC_length (state_t, output_states_vect));
7649 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7651 state_t s = VEC_index (state_t, output_states_vect, i);
7652 arc = first_out_arc (s);
7653 gcc_assert (arc);
7654 if (next_out_arc (arc) == NULL
7655 && (arc->insn->insn_reserv_decl
7656 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7658 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7659 automaton->locked_states++;
7661 else
7662 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7664 if (automaton->locked_states == 0)
7665 return;
7667 fprintf (output_file, "/* Vector for locked state flags. */\n");
7668 fprintf (output_file, "static const ");
7669 output_range_type (output_file, 0, 1);
7670 fprintf (output_file, " ");
7671 output_dead_lock_vect_name (output_file, automaton);
7672 fprintf (output_file, "[] = {\n");
7673 output_vect (dead_lock_vect);
7674 fprintf (output_file, "};\n\n");
7675 VEC_free (state_t, heap, output_states_vect);
7676 VEC_free (vect_el_t, heap, dead_lock_vect);
7679 /* Form and output vector representing reserved units of the states of
7680 AUTOMATON. */
7681 static void
7682 output_reserved_units_table (automaton_t automaton)
7684 vla_hwint_t reserved_units_table = 0;
7685 int state_byte_size;
7686 int reserved_units_size;
7687 size_t n;
7688 int i;
7690 if (description->query_units_num == 0)
7691 return;
7693 /* Create vect of pointers to states. */
7694 output_states_vect = 0;
7695 pass_states (automaton, add_states_vect_el);
7696 /* Create vector. */
7697 state_byte_size = (description->query_units_num + 7) / 8;
7698 reserved_units_size = (VEC_length (state_t, output_states_vect)
7699 * state_byte_size);
7701 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7703 for (i = 0; i < reserved_units_size; i++)
7704 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7705 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7707 state_t s = VEC_index (state_t, output_states_vect, n);
7708 for (i = 0; i < description->units_num; i++)
7709 if (units_array [i]->query_p
7710 && first_cycle_unit_presence (s, i))
7712 int ri = (s->order_state_num * state_byte_size
7713 + units_array [i]->query_num / 8);
7714 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7716 x += 1 << (units_array [i]->query_num % 8);
7717 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7720 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7721 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7722 fprintf (output_file, "static const ");
7723 output_range_type (output_file, 0, 255);
7724 fprintf (output_file, " ");
7725 output_reserved_units_table_name (output_file, automaton);
7726 fprintf (output_file, "[] = {\n");
7727 output_vect (reserved_units_table);
7728 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7729 CPU_UNITS_QUERY_MACRO_NAME);
7731 VEC_free (state_t, heap, output_states_vect);
7732 VEC_free (vect_el_t, heap, reserved_units_table);
7735 /* The function outputs all tables representing DFA(s) used for fast
7736 pipeline hazards recognition. */
7737 static void
7738 output_tables (void)
7740 automaton_t automaton;
7742 for (automaton = description->first_automaton;
7743 automaton != NULL;
7744 automaton = automaton->next_automaton)
7746 output_translate_vect (automaton);
7747 output_trans_table (automaton);
7748 output_min_issue_delay_table (automaton);
7749 output_dead_lock_vect (automaton);
7750 output_reserved_units_table (automaton);
7752 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7753 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7756 /* The function outputs definition and value of PHR interface variable
7757 `max_insn_queue_index'. Its value is not less than maximal queue
7758 length needed for the insn scheduler. */
7759 static void
7760 output_max_insn_queue_index_def (void)
7762 int i, max, latency;
7763 decl_t decl;
7765 max = description->max_insn_reserv_cycles;
7766 for (i = 0; i < description->decls_num; i++)
7768 decl = description->decls [i];
7769 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7771 latency = DECL_INSN_RESERV (decl)->default_latency;
7772 if (latency > max)
7773 max = latency;
7775 else if (decl->mode == dm_bypass)
7777 latency = DECL_BYPASS (decl)->latency;
7778 if (latency > max)
7779 max = latency;
7782 for (i = 0; (1 << i) <= max; i++)
7784 gcc_assert (i >= 0);
7785 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7786 (1 << i) - 1);
7789 /* The function outputs switch cases for insn reservations using
7790 function *output_automata_list_code. */
7791 static void
7792 output_insn_code_cases (void (*output_automata_list_code)
7793 (automata_list_el_t))
7795 decl_t decl, decl2;
7796 int i, j;
7798 for (i = 0; i < description->decls_num; i++)
7800 decl = description->decls [i];
7801 if (decl->mode == dm_insn_reserv)
7802 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7804 for (i = 0; i < description->decls_num; i++)
7806 decl = description->decls [i];
7807 if (decl->mode == dm_insn_reserv
7808 && !DECL_INSN_RESERV (decl)->processed_p)
7810 for (j = i; j < description->decls_num; j++)
7812 decl2 = description->decls [j];
7813 if (decl2->mode == dm_insn_reserv
7814 && (DECL_INSN_RESERV (decl2)->important_automata_list
7815 == DECL_INSN_RESERV (decl)->important_automata_list))
7817 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7818 fprintf (output_file, " case %d: /* %s */\n",
7819 DECL_INSN_RESERV (decl2)->insn_num,
7820 DECL_INSN_RESERV (decl2)->name);
7823 (*output_automata_list_code)
7824 (DECL_INSN_RESERV (decl)->important_automata_list);
7830 /* The function outputs a code for evaluation of a minimal delay of
7831 issue of insns which have reservations in given AUTOMATA_LIST. */
7832 static void
7833 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7835 automata_list_el_t el;
7836 automaton_t automaton;
7838 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7840 automaton = el->automaton;
7841 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7842 output_min_issue_delay_vect_name (output_file, automaton);
7843 fprintf (output_file,
7844 (automaton->min_issue_delay_table_compression_factor != 1
7845 ? " [(" : " ["));
7846 output_translate_vect_name (output_file, automaton);
7847 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7848 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7849 output_chip_member_name (output_file, automaton);
7850 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7851 if (automaton->min_issue_delay_table_compression_factor == 1)
7852 fprintf (output_file, "];\n");
7853 else
7855 fprintf (output_file, ") / %d];\n",
7856 automaton->min_issue_delay_table_compression_factor);
7857 fprintf (output_file, " %s = (%s >> (8 - ((",
7858 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7859 output_translate_vect_name (output_file, automaton);
7860 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7861 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7862 output_chip_member_name (output_file, automaton);
7863 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7864 fprintf
7865 (output_file, " %% %d + 1) * %d)) & %d;\n",
7866 automaton->min_issue_delay_table_compression_factor,
7867 8 / automaton->min_issue_delay_table_compression_factor,
7868 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7869 - 1);
7871 if (el == automata_list)
7872 fprintf (output_file, " %s = %s;\n",
7873 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7874 else
7876 fprintf (output_file, " if (%s > %s)\n",
7877 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7878 fprintf (output_file, " %s = %s;\n",
7879 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7882 fprintf (output_file, " break;\n\n");
7885 /* Output function `internal_min_issue_delay'. */
7886 static void
7887 output_internal_min_issue_delay_func (void)
7889 fprintf (output_file,
7890 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7891 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7892 CHIP_NAME, CHIP_PARAMETER_NAME);
7893 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7894 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7895 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7896 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7897 fprintf (output_file,
7898 "\n default:\n %s = -1;\n break;\n }\n",
7899 RESULT_VARIABLE_NAME);
7900 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7901 fprintf (output_file, "}\n\n");
7904 /* The function outputs a code changing state after issue of insns
7905 which have reservations in given AUTOMATA_LIST. */
7906 static void
7907 output_automata_list_transition_code (automata_list_el_t automata_list)
7909 automata_list_el_t el, next_el;
7911 fprintf (output_file, " {\n");
7912 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7913 for (el = automata_list;; el = next_el)
7915 next_el = el->next_automata_list_el;
7916 if (next_el == NULL)
7917 break;
7918 fprintf (output_file, " ");
7919 output_state_member_type (output_file, el->automaton);
7920 fprintf (output_file, " ");
7921 output_temp_chip_member_name (output_file, el->automaton);
7922 fprintf (output_file, ";\n");
7924 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7925 if (comb_vect_p (el->automaton->trans_table))
7927 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7928 output_trans_base_vect_name (output_file, el->automaton);
7929 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7930 output_chip_member_name (output_file, el->automaton);
7931 fprintf (output_file, "] + ");
7932 output_translate_vect_name (output_file, el->automaton);
7933 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7934 fprintf (output_file, " if (");
7935 output_trans_check_vect_name (output_file, el->automaton);
7936 fprintf (output_file, " [%s] != %s->",
7937 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7938 output_chip_member_name (output_file, el->automaton);
7939 fprintf (output_file, ")\n");
7940 fprintf (output_file, " return %s (%s, %s);\n",
7941 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7942 CHIP_PARAMETER_NAME);
7943 fprintf (output_file, " else\n");
7944 fprintf (output_file, " ");
7945 if (el->next_automata_list_el != NULL)
7946 output_temp_chip_member_name (output_file, el->automaton);
7947 else
7949 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7950 output_chip_member_name (output_file, el->automaton);
7952 fprintf (output_file, " = ");
7953 output_trans_comb_vect_name (output_file, el->automaton);
7954 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7956 else
7958 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7959 output_trans_full_vect_name (output_file, el->automaton);
7960 fprintf (output_file, " [");
7961 output_translate_vect_name (output_file, el->automaton);
7962 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7963 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7964 output_chip_member_name (output_file, el->automaton);
7965 fprintf (output_file, " * %d];\n",
7966 el->automaton->insn_equiv_classes_num);
7967 fprintf (output_file, " if (%s >= %d)\n",
7968 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7969 fprintf (output_file, " return %s (%s, %s);\n",
7970 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7971 CHIP_PARAMETER_NAME);
7972 fprintf (output_file, " else\n ");
7973 if (el->next_automata_list_el != NULL)
7974 output_temp_chip_member_name (output_file, el->automaton);
7975 else
7977 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7978 output_chip_member_name (output_file, el->automaton);
7980 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7982 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7983 for (el = automata_list;; el = next_el)
7985 next_el = el->next_automata_list_el;
7986 if (next_el == NULL)
7987 break;
7988 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7989 output_chip_member_name (output_file, el->automaton);
7990 fprintf (output_file, " = ");
7991 output_temp_chip_member_name (output_file, el->automaton);
7992 fprintf (output_file, ";\n");
7994 fprintf (output_file, " return -1;\n");
7995 fprintf (output_file, " }\n");
7998 /* Output function `internal_state_transition'. */
7999 static void
8000 output_internal_trans_func (void)
8002 fprintf (output_file,
8003 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8004 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8005 CHIP_NAME, CHIP_PARAMETER_NAME);
8006 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8007 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8008 output_insn_code_cases (output_automata_list_transition_code);
8009 fprintf (output_file, "\n default:\n return -1;\n }\n");
8010 fprintf (output_file, "}\n\n");
8013 /* Output code
8015 if (insn != 0)
8017 insn_code = dfa_insn_code (insn);
8018 if (insn_code > DFA__ADVANCE_CYCLE)
8019 return code;
8021 else
8022 insn_code = DFA__ADVANCE_CYCLE;
8024 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8025 code denotes CODE. */
8026 static void
8027 output_internal_insn_code_evaluation (const char *insn_name,
8028 const char *insn_code_name,
8029 int code)
8031 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8032 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8033 DFA_INSN_CODE_FUNC_NAME, insn_name);
8034 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8035 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8036 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8037 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8041 /* This function outputs `dfa_insn_code' and its helper function
8042 `dfa_insn_code_enlarge'. */
8043 static void
8044 output_dfa_insn_code_func (void)
8046 /* Emacs c-mode gets really confused if there's a { or } in column 0
8047 inside a string, so don't do that. */
8048 fprintf (output_file, "\
8049 static void\n\
8050 dfa_insn_code_enlarge (int uid)\n\
8051 {\n\
8052 int i = %s;\n\
8053 %s = 2 * uid;\n\
8054 %s = XRESIZEVEC (int, %s,\n\
8055 %s);\n\
8056 for (; i < %s; i++)\n\
8057 %s[i] = -1;\n}\n\n",
8058 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8059 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8060 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8061 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8062 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8063 DFA_INSN_CODES_VARIABLE_NAME);
8064 fprintf (output_file, "\
8065 static inline int\n%s (rtx %s)\n\
8066 {\n\
8067 int uid = INSN_UID (%s);\n\
8068 int %s;\n\n",
8069 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8070 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8072 fprintf (output_file,
8073 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8074 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8075 fprintf (output_file, " %s = %s[uid];\n",
8076 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8077 fprintf (output_file, "\
8078 if (%s < 0)\n\
8079 {\n\
8080 %s = %s (%s);\n\
8081 %s[uid] = %s;\n\
8082 }\n",
8083 INTERNAL_INSN_CODE_NAME,
8084 INTERNAL_INSN_CODE_NAME,
8085 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8086 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8087 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8090 /* The function outputs PHR interface function `state_transition'. */
8091 static void
8092 output_trans_func (void)
8094 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8095 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8096 INSN_PARAMETER_NAME);
8097 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8098 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8099 INTERNAL_INSN_CODE_NAME, -1);
8100 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8101 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8104 /* Output function `min_issue_delay'. */
8105 static void
8106 output_min_issue_delay_func (void)
8108 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8109 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8110 INSN_PARAMETER_NAME);
8111 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8112 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8113 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8114 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8115 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8116 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8117 fprintf (output_file, " }\n else\n %s = %s;\n",
8118 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8119 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8120 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8121 CHIP_NAME, STATE_NAME);
8122 fprintf (output_file, "}\n\n");
8125 /* Output function `internal_dead_lock'. */
8126 static void
8127 output_internal_dead_lock_func (void)
8129 automaton_t automaton;
8131 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8132 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8133 fprintf (output_file, "{\n");
8134 for (automaton = description->first_automaton;
8135 automaton != NULL;
8136 automaton = automaton->next_automaton)
8137 if (automaton->locked_states)
8139 fprintf (output_file, " if (");
8140 output_dead_lock_vect_name (output_file, automaton);
8141 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8142 output_chip_member_name (output_file, automaton);
8143 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8145 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8148 /* The function outputs PHR interface function `state_dead_lock_p'. */
8149 static void
8150 output_dead_lock_func (void)
8152 fprintf (output_file, "int\n%s (%s %s)\n",
8153 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8154 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8155 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8158 /* Output function `internal_reset'. */
8159 static void
8160 output_internal_reset_func (void)
8162 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8163 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8164 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8165 CHIP_PARAMETER_NAME, CHIP_NAME);
8168 /* The function outputs PHR interface function `state_size'. */
8169 static void
8170 output_size_func (void)
8172 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8173 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8176 /* The function outputs PHR interface function `state_reset'. */
8177 static void
8178 output_reset_func (void)
8180 fprintf (output_file, "void\n%s (%s %s)\n",
8181 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8182 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8183 CHIP_NAME, STATE_NAME);
8186 /* Output function `min_insn_conflict_delay'. */
8187 static void
8188 output_min_insn_conflict_delay_func (void)
8190 fprintf (output_file,
8191 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8192 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8193 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8194 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8195 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8196 INTERNAL_INSN2_CODE_NAME);
8197 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8198 INTERNAL_INSN_CODE_NAME, 0);
8199 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8200 INTERNAL_INSN2_CODE_NAME, 0);
8201 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8202 CHIP_NAME, STATE_NAME, CHIP_NAME);
8203 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8204 fprintf (output_file, " transition = %s (%s, &%s);\n",
8205 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8206 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8207 fprintf (output_file, " return %s (%s, &%s);\n",
8208 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8209 CHIP_NAME);
8210 fprintf (output_file, "}\n\n");
8213 /* Output the array holding default latency values. These are used in
8214 insn_latency and maximal_insn_latency function implementations. */
8215 static void
8216 output_default_latencies (void)
8218 int i, j, col;
8219 decl_t decl;
8220 const char *tabletype = "unsigned char";
8222 /* Find the smallest integer type that can hold all the default
8223 latency values. */
8224 for (i = 0; i < description->decls_num; i++)
8225 if (description->decls[i]->mode == dm_insn_reserv)
8227 decl = description->decls[i];
8228 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8229 && tabletype[0] != 'i') /* Don't shrink it. */
8230 tabletype = "unsigned short";
8231 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8232 tabletype = "int";
8235 fprintf (output_file, " static const %s default_latencies[] =\n {",
8236 tabletype);
8238 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8239 if (description->decls[i]->mode == dm_insn_reserv
8240 && description->decls[i] != advance_cycle_insn_decl)
8242 if ((col = (col+1) % 8) == 0)
8243 fputs ("\n ", output_file);
8244 decl = description->decls[i];
8245 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8246 fprintf (output_file, "% 4d,",
8247 DECL_INSN_RESERV (decl)->default_latency);
8249 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8250 fputs ("\n };\n", output_file);
8253 /* Output function `internal_insn_latency'. */
8254 static void
8255 output_internal_insn_latency_func (void)
8257 int i;
8258 decl_t decl;
8259 struct bypass_decl *bypass;
8261 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",
8262 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8263 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8264 INSN2_PARAMETER_NAME);
8265 fprintf (output_file, "{\n");
8267 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8269 fputs (" return 0;\n}\n\n", output_file);
8270 return;
8273 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8274 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8275 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8277 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8278 for (i = 0; i < description->decls_num; i++)
8279 if (description->decls[i]->mode == dm_insn_reserv
8280 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8282 decl = description->decls [i];
8283 fprintf (output_file,
8284 " case %d:\n switch (%s)\n {\n",
8285 DECL_INSN_RESERV (decl)->insn_num,
8286 INTERNAL_INSN2_CODE_NAME);
8287 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8288 bypass != NULL;
8289 bypass = bypass->next)
8291 gcc_assert (bypass->in_insn_reserv->insn_num
8292 != (DECL_INSN_RESERV
8293 (advance_cycle_insn_decl)->insn_num));
8294 fprintf (output_file, " case %d:\n",
8295 bypass->in_insn_reserv->insn_num);
8296 for (;;)
8298 if (bypass->bypass_guard_name == NULL)
8300 gcc_assert (bypass->next == NULL
8301 || (bypass->in_insn_reserv
8302 != bypass->next->in_insn_reserv));
8303 fprintf (output_file, " return %d;\n",
8304 bypass->latency);
8306 else
8308 fprintf (output_file,
8309 " if (%s (%s, %s))\n",
8310 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8311 INSN2_PARAMETER_NAME);
8312 fprintf (output_file, " return %d;\n",
8313 bypass->latency);
8315 if (bypass->next == NULL
8316 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8317 break;
8318 bypass = bypass->next;
8320 if (bypass->bypass_guard_name != NULL)
8321 fprintf (output_file, " break;\n");
8323 fputs (" }\n break;\n", output_file);
8326 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8327 INTERNAL_INSN_CODE_NAME);
8330 /* Output function `internal_maximum_insn_latency'. */
8331 static void
8332 output_internal_maximal_insn_latency_func (void)
8334 decl_t decl;
8335 struct bypass_decl *bypass;
8336 int i;
8337 int max;
8339 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8340 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8341 INSN_PARAMETER_NAME);
8342 fprintf (output_file, "{\n");
8344 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8346 fputs (" return 0;\n}\n\n", output_file);
8347 return;
8350 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8351 for (i = 0; i < description->decls_num; i++)
8352 if (description->decls[i]->mode == dm_insn_reserv
8353 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8355 decl = description->decls [i];
8356 max = DECL_INSN_RESERV (decl)->default_latency;
8357 fprintf (output_file,
8358 " case %d: {",
8359 DECL_INSN_RESERV (decl)->insn_num);
8360 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8361 bypass != NULL;
8362 bypass = bypass->next)
8364 if (bypass->latency > max)
8365 max = bypass->latency;
8367 fprintf (output_file, " return %d; }\n break;\n", max);
8370 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8371 INTERNAL_INSN_CODE_NAME);
8374 /* The function outputs PHR interface function `insn_latency'. */
8375 static void
8376 output_insn_latency_func (void)
8378 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8379 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8380 fprintf (output_file, "{\n int %s, %s;\n",
8381 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8382 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8383 INTERNAL_INSN_CODE_NAME, 0);
8384 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8385 INTERNAL_INSN2_CODE_NAME, 0);
8386 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8387 INTERNAL_INSN_LATENCY_FUNC_NAME,
8388 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8389 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8392 /* The function outputs PHR interface function `maximal_insn_latency'. */
8393 static void
8394 output_maximal_insn_latency_func (void)
8396 fprintf (output_file, "int\n%s (rtx %s)\n",
8397 "maximal_insn_latency", INSN_PARAMETER_NAME);
8398 fprintf (output_file, "{\n int %s;\n",
8399 INTERNAL_INSN_CODE_NAME);
8400 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8401 INTERNAL_INSN_CODE_NAME, 0);
8402 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8403 "internal_maximal_insn_latency",
8404 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8407 /* The function outputs PHR interface function `print_reservation'. */
8408 static void
8409 output_print_reservation_func (void)
8411 decl_t decl;
8412 int i, j;
8414 fprintf (output_file,
8415 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8416 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8417 INSN_PARAMETER_NAME);
8419 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8421 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8422 NOTHING_NAME, FILE_PARAMETER_NAME);
8423 return;
8427 fputs (" static const char *const reservation_names[] =\n {",
8428 output_file);
8430 for (i = 0, j = 0; i < description->decls_num; i++)
8432 decl = description->decls [i];
8433 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8435 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8436 j++;
8438 fprintf (output_file, "\n \"%s\",",
8439 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8440 finish_regexp_representation ();
8443 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8445 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8446 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8448 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8449 INSN_PARAMETER_NAME,
8450 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8451 fprintf (output_file, " else\n\
8452 {\n\
8453 %s = %s (%s);\n\
8454 if (%s > %s)\n\
8455 %s = %s;\n\
8456 }\n",
8457 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8458 INSN_PARAMETER_NAME,
8459 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8460 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8462 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8463 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8466 /* The following function is used to sort unit declaration by their
8467 names. */
8468 static int
8469 units_cmp (const void *unit1, const void *unit2)
8471 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8472 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8474 return strcmp (u1->name, u2->name);
8477 /* The following macro value is name of struct containing unit name
8478 and unit code. */
8479 #define NAME_CODE_STRUCT_NAME "name_code"
8481 /* The following macro value is name of table of struct name_code. */
8482 #define NAME_CODE_TABLE_NAME "name_code_table"
8484 /* The following macro values are member names for struct name_code. */
8485 #define NAME_MEMBER_NAME "name"
8486 #define CODE_MEMBER_NAME "code"
8488 /* The following macro values are local variable names for function
8489 `get_cpu_unit_code'. */
8490 #define CMP_VARIABLE_NAME "cmp"
8491 #define LOW_VARIABLE_NAME "l"
8492 #define MIDDLE_VARIABLE_NAME "m"
8493 #define HIGH_VARIABLE_NAME "h"
8495 /* The following function outputs function to obtain internal cpu unit
8496 code by the cpu unit name. */
8497 static void
8498 output_get_cpu_unit_code_func (void)
8500 int i;
8501 unit_decl_t *units;
8503 fprintf (output_file, "int\n%s (const char *%s)\n",
8504 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8505 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8506 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8507 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8508 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8509 fprintf (output_file, " static struct %s %s [] =\n {\n",
8510 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8511 units = XNEWVEC (unit_decl_t, description->units_num);
8512 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8513 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8514 for (i = 0; i < description->units_num; i++)
8515 if (units [i]->query_p)
8516 fprintf (output_file, " {\"%s\", %d},\n",
8517 units[i]->name, units[i]->query_num);
8518 fprintf (output_file, " };\n\n");
8519 fprintf (output_file, " /* The following is binary search: */\n");
8520 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8521 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8522 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8523 fprintf (output_file, " while (%s <= %s)\n {\n",
8524 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8525 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8526 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8527 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8528 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8529 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8530 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8531 fprintf (output_file, " %s = %s - 1;\n",
8532 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8533 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8534 fprintf (output_file, " %s = %s + 1;\n",
8535 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8536 fprintf (output_file, " else\n");
8537 fprintf (output_file, " return %s [%s].%s;\n }\n",
8538 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8539 fprintf (output_file, " return -1;\n}\n\n");
8540 free (units);
8543 /* The following function outputs function to check reservation of cpu
8544 unit (its internal code will be passed as the function argument) in
8545 given cpu state. */
8546 static void
8547 output_cpu_unit_reservation_p (void)
8549 automaton_t automaton;
8551 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8552 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8553 STATE_TYPE_NAME, STATE_NAME,
8554 CPU_CODE_PARAMETER_NAME);
8555 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8556 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8557 description->query_units_num);
8558 if (description->query_units_num > 0)
8559 for (automaton = description->first_automaton;
8560 automaton != NULL;
8561 automaton = automaton->next_automaton)
8563 fprintf (output_file, " if ((");
8564 output_reserved_units_table_name (output_file, automaton);
8565 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8566 output_chip_member_name (output_file, automaton);
8567 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8568 (description->query_units_num + 7) / 8,
8569 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8570 fprintf (output_file, " return 1;\n");
8572 fprintf (output_file, " return 0;\n}\n\n");
8575 /* The following function outputs a function to check if insn
8576 has a dfa reservation. */
8577 static void
8578 output_insn_has_dfa_reservation_p (void)
8580 fprintf (output_file,
8581 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8582 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8583 INSN_PARAMETER_NAME);
8585 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8587 fprintf (output_file, " return false;\n}\n\n");
8588 return;
8591 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8593 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8594 INSN_PARAMETER_NAME,
8595 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8596 fprintf (output_file, " else\n\
8597 {\n\
8598 %s = %s (%s);\n\
8599 if (%s > %s)\n\
8600 %s = %s;\n\
8601 }\n\n",
8602 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8603 INSN_PARAMETER_NAME,
8604 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8605 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8607 fprintf (output_file, " return %s != %s;\n}\n\n",
8608 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8611 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8612 and 'dfa_clear_single_insn_cache'. */
8613 static void
8614 output_dfa_clean_insn_cache_func (void)
8616 fprintf (output_file,
8617 "void\n%s (void)\n{\n int %s;\n\n",
8618 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8619 fprintf (output_file,
8620 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8621 I_VARIABLE_NAME, I_VARIABLE_NAME,
8622 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8623 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8625 fprintf (output_file,
8626 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8627 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8628 I_VARIABLE_NAME);
8629 fprintf (output_file,
8630 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8631 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8632 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8633 I_VARIABLE_NAME);
8636 /* The function outputs PHR interface function `dfa_start'. */
8637 static void
8638 output_dfa_start_func (void)
8640 fprintf (output_file,
8641 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8642 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8643 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8644 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8645 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8648 /* The function outputs PHR interface function `dfa_finish'. */
8649 static void
8650 output_dfa_finish_func (void)
8652 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8653 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8658 /* The page contains code for output description file (readable
8659 representation of original description and generated DFA(s). */
8661 /* The function outputs string representation of IR reservation. */
8662 static void
8663 output_regexp (regexp_t regexp)
8665 fprintf (output_description_file, "%s", regexp_representation (regexp));
8666 finish_regexp_representation ();
8669 /* Output names of units in LIST separated by comma. */
8670 static void
8671 output_unit_set_el_list (unit_set_el_t list)
8673 unit_set_el_t el;
8675 for (el = list; el != NULL; el = el->next_unit_set_el)
8677 if (el != list)
8678 fprintf (output_description_file, ", ");
8679 fprintf (output_description_file, "%s", el->unit_decl->name);
8683 /* Output patterns in LIST separated by comma. */
8684 static void
8685 output_pattern_set_el_list (pattern_set_el_t list)
8687 pattern_set_el_t el;
8688 int i;
8690 for (el = list; el != NULL; el = el->next_pattern_set_el)
8692 if (el != list)
8693 fprintf (output_description_file, ", ");
8694 for (i = 0; i < el->units_num; i++)
8695 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8696 el->unit_decls [i]->name);
8700 /* The function outputs string representation of IR define_reservation
8701 and define_insn_reservation. */
8702 static void
8703 output_description (void)
8705 decl_t decl;
8706 int i;
8708 for (i = 0; i < description->decls_num; i++)
8710 decl = description->decls [i];
8711 if (decl->mode == dm_unit)
8713 if (DECL_UNIT (decl)->excl_list != NULL)
8715 fprintf (output_description_file, "unit %s exclusion_set: ",
8716 DECL_UNIT (decl)->name);
8717 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8718 fprintf (output_description_file, "\n");
8720 if (DECL_UNIT (decl)->presence_list != NULL)
8722 fprintf (output_description_file, "unit %s presence_set: ",
8723 DECL_UNIT (decl)->name);
8724 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8725 fprintf (output_description_file, "\n");
8727 if (DECL_UNIT (decl)->final_presence_list != NULL)
8729 fprintf (output_description_file, "unit %s final_presence_set: ",
8730 DECL_UNIT (decl)->name);
8731 output_pattern_set_el_list
8732 (DECL_UNIT (decl)->final_presence_list);
8733 fprintf (output_description_file, "\n");
8735 if (DECL_UNIT (decl)->absence_list != NULL)
8737 fprintf (output_description_file, "unit %s absence_set: ",
8738 DECL_UNIT (decl)->name);
8739 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8740 fprintf (output_description_file, "\n");
8742 if (DECL_UNIT (decl)->final_absence_list != NULL)
8744 fprintf (output_description_file, "unit %s final_absence_set: ",
8745 DECL_UNIT (decl)->name);
8746 output_pattern_set_el_list
8747 (DECL_UNIT (decl)->final_absence_list);
8748 fprintf (output_description_file, "\n");
8752 fprintf (output_description_file, "\n");
8753 for (i = 0; i < description->decls_num; i++)
8755 decl = description->decls [i];
8756 if (decl->mode == dm_reserv)
8758 fprintf (output_description_file, "reservation %s: ",
8759 DECL_RESERV (decl)->name);
8760 output_regexp (DECL_RESERV (decl)->regexp);
8761 fprintf (output_description_file, "\n");
8763 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8765 fprintf (output_description_file, "insn reservation %s ",
8766 DECL_INSN_RESERV (decl)->name);
8767 print_rtl (output_description_file,
8768 DECL_INSN_RESERV (decl)->condexp);
8769 fprintf (output_description_file, ": ");
8770 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8771 fprintf (output_description_file, "\n");
8773 else if (decl->mode == dm_bypass)
8774 fprintf (output_description_file, "bypass %d %s %s\n",
8775 DECL_BYPASS (decl)->latency,
8776 DECL_BYPASS (decl)->out_insn_name,
8777 DECL_BYPASS (decl)->in_insn_name);
8779 fprintf (output_description_file, "\n\f\n");
8782 /* The function outputs name of AUTOMATON. */
8783 static void
8784 output_automaton_name (FILE *f, automaton_t automaton)
8786 if (automaton->corresponding_automaton_decl == NULL)
8787 fprintf (f, "#%d", automaton->automaton_order_num);
8788 else
8789 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8792 /* Maximal length of line for pretty printing into description
8793 file. */
8794 #define MAX_LINE_LENGTH 70
8796 /* The function outputs units name belonging to AUTOMATON. */
8797 static void
8798 output_automaton_units (automaton_t automaton)
8800 decl_t decl;
8801 const char *name;
8802 int curr_line_length;
8803 int there_is_an_automaton_unit;
8804 int i;
8806 fprintf (output_description_file, "\n Corresponding units:\n");
8807 fprintf (output_description_file, " ");
8808 curr_line_length = 4;
8809 there_is_an_automaton_unit = 0;
8810 for (i = 0; i < description->decls_num; i++)
8812 decl = description->decls [i];
8813 if (decl->mode == dm_unit
8814 && (DECL_UNIT (decl)->corresponding_automaton_num
8815 == automaton->automaton_order_num))
8817 there_is_an_automaton_unit = 1;
8818 name = DECL_UNIT (decl)->name;
8819 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8821 curr_line_length = strlen (name) + 4;
8822 fprintf (output_description_file, "\n ");
8824 else
8826 curr_line_length += strlen (name) + 1;
8827 fprintf (output_description_file, " ");
8829 fprintf (output_description_file, "%s", name);
8832 if (!there_is_an_automaton_unit)
8833 fprintf (output_description_file, "<None>");
8834 fprintf (output_description_file, "\n\n");
8837 /* The following variable is used for forming array of all possible cpu unit
8838 reservations described by the current DFA state. */
8839 static VEC(reserv_sets_t, heap) *state_reservs;
8841 /* The function forms `state_reservs' for STATE. */
8842 static void
8843 add_state_reservs (state_t state)
8845 alt_state_t curr_alt_state;
8847 if (state->component_states != NULL)
8848 for (curr_alt_state = state->component_states;
8849 curr_alt_state != NULL;
8850 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8851 add_state_reservs (curr_alt_state->state);
8852 else
8853 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
8856 /* The function outputs readable representation of all out arcs of
8857 STATE. */
8858 static void
8859 output_state_arcs (state_t state)
8861 arc_t arc;
8862 ainsn_t ainsn;
8863 const char *insn_name;
8864 int curr_line_length;
8866 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8868 ainsn = arc->insn;
8869 gcc_assert (ainsn->first_insn_with_same_reservs);
8870 fprintf (output_description_file, " ");
8871 curr_line_length = 7;
8872 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8875 insn_name = ainsn->insn_reserv_decl->name;
8876 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8878 if (ainsn != arc->insn)
8880 fprintf (output_description_file, ",\n ");
8881 curr_line_length = strlen (insn_name) + 6;
8883 else
8884 curr_line_length += strlen (insn_name);
8886 else
8888 curr_line_length += strlen (insn_name);
8889 if (ainsn != arc->insn)
8891 curr_line_length += 2;
8892 fprintf (output_description_file, ", ");
8895 fprintf (output_description_file, "%s", insn_name);
8896 ainsn = ainsn->next_same_reservs_insn;
8898 while (ainsn != NULL);
8899 fprintf (output_description_file, " %d \n",
8900 arc->to_state->order_state_num);
8902 fprintf (output_description_file, "\n");
8905 /* The following function is used for sorting possible cpu unit
8906 reservation of a DFA state. */
8907 static int
8908 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8910 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8911 *(const_reserv_sets_t const*) reservs_ptr_2);
8914 /* The following function is used for sorting possible cpu unit
8915 reservation of a DFA state. */
8916 static void
8917 remove_state_duplicate_reservs (void)
8919 size_t i, j;
8921 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8922 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8923 VEC_index (reserv_sets_t, state_reservs, i)))
8925 j++;
8926 VEC_replace (reserv_sets_t, state_reservs, j,
8927 VEC_index (reserv_sets_t, state_reservs, i));
8929 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8932 /* The following function output readable representation of DFA(s)
8933 state used for fast recognition of pipeline hazards. State is
8934 described by possible (current and scheduled) cpu unit
8935 reservations. */
8936 static void
8937 output_state (state_t state)
8939 size_t i;
8941 state_reservs = 0;
8943 fprintf (output_description_file, " State #%d", state->order_state_num);
8944 fprintf (output_description_file,
8945 state->new_cycle_p ? " (new cycle)\n" : "\n");
8946 add_state_reservs (state);
8947 qsort (VEC_address (reserv_sets_t, state_reservs),
8948 VEC_length (reserv_sets_t, state_reservs),
8949 sizeof (reserv_sets_t), state_reservs_cmp);
8950 remove_state_duplicate_reservs ();
8951 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8953 fprintf (output_description_file, " ");
8954 output_reserv_sets (output_description_file,
8955 VEC_index (reserv_sets_t, state_reservs, i));
8956 fprintf (output_description_file, "\n");
8958 fprintf (output_description_file, "\n");
8959 output_state_arcs (state);
8960 VEC_free (reserv_sets_t, heap, state_reservs);
8963 /* The following function output readable representation of
8964 DFAs used for fast recognition of pipeline hazards. */
8965 static void
8966 output_automaton_descriptions (void)
8968 automaton_t automaton;
8970 for (automaton = description->first_automaton;
8971 automaton != NULL;
8972 automaton = automaton->next_automaton)
8974 fprintf (output_description_file, "\nAutomaton ");
8975 output_automaton_name (output_description_file, automaton);
8976 fprintf (output_description_file, "\n");
8977 output_automaton_units (automaton);
8978 pass_states (automaton, output_state);
8984 /* The page contains top level function for generation DFA(s) used for
8985 PHR. */
8987 /* The function outputs statistics about work of different phases of
8988 DFA generator. */
8989 static void
8990 output_statistics (FILE *f)
8992 automaton_t automaton;
8993 int states_num;
8994 #ifndef NDEBUG
8995 int transition_comb_vect_els = 0;
8996 int transition_full_vect_els = 0;
8997 int min_issue_delay_vect_els = 0;
8998 int locked_states = 0;
8999 #endif
9001 for (automaton = description->first_automaton;
9002 automaton != NULL;
9003 automaton = automaton->next_automaton)
9005 fprintf (f, "\nAutomaton ");
9006 output_automaton_name (f, automaton);
9007 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9008 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9009 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9010 automaton->DFA_states_num, automaton->DFA_arcs_num);
9011 states_num = automaton->DFA_states_num;
9012 if (!no_minimization_flag)
9014 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9015 automaton->minimal_DFA_states_num,
9016 automaton->minimal_DFA_arcs_num);
9017 states_num = automaton->minimal_DFA_states_num;
9019 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9020 description->insns_num, automaton->insn_equiv_classes_num);
9021 fprintf (f, " %d locked states\n", automaton->locked_states);
9022 #ifndef NDEBUG
9023 fprintf
9024 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9025 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9026 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9027 (comb_vect_p (automaton->trans_table)
9028 ? "use comb vect" : "use simple vect"));
9029 fprintf
9030 (f, "%5ld min delay table els, compression factor %d\n",
9031 (long) states_num * automaton->insn_equiv_classes_num,
9032 automaton->min_issue_delay_table_compression_factor);
9033 transition_comb_vect_els
9034 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9035 transition_full_vect_els
9036 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9037 min_issue_delay_vect_els
9038 += states_num * automaton->insn_equiv_classes_num;
9039 locked_states
9040 += automaton->locked_states;
9041 #endif
9043 #ifndef NDEBUG
9044 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9045 allocated_states_num, allocated_arcs_num);
9046 fprintf (f, "%5d all allocated alternative states\n",
9047 allocated_alt_states_num);
9048 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9049 transition_comb_vect_els, transition_full_vect_els);
9050 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9051 fprintf (f, "%5d all locked states\n", locked_states);
9052 #endif
9055 /* The function output times of work of different phases of DFA
9056 generator. */
9057 static void
9058 output_time_statistics (FILE *f)
9060 fprintf (f, "\n transformation: ");
9061 print_active_time (f, transform_time);
9062 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9063 print_active_time (f, NDFA_time);
9064 if (ndfa_flag)
9066 fprintf (f, ", NDFA -> DFA: ");
9067 print_active_time (f, NDFA_to_DFA_time);
9069 fprintf (f, "\n DFA minimization: ");
9070 print_active_time (f, minimize_time);
9071 fprintf (f, ", making insn equivalence: ");
9072 print_active_time (f, equiv_time);
9073 fprintf (f, "\n all automaton generation: ");
9074 print_active_time (f, automaton_generation_time);
9075 fprintf (f, ", output: ");
9076 print_active_time (f, output_time);
9077 fprintf (f, "\n");
9080 /* The function generates DFA (deterministic finite state automaton)
9081 for fast recognition of pipeline hazards. No errors during
9082 checking must be fixed before this function call. */
9083 static void
9084 generate (void)
9086 automata_num = split_argument;
9087 if (description->units_num < automata_num)
9088 automata_num = description->units_num;
9089 initiate_states ();
9090 initiate_arcs ();
9091 initiate_automata_lists ();
9092 initiate_pass_states ();
9093 initiate_excl_sets ();
9094 initiate_presence_absence_pattern_sets ();
9095 automaton_generation_time = create_ticker ();
9096 create_automata ();
9097 ticker_off (&automaton_generation_time);
9102 /* This page mainly contains top level functions of pipeline hazards
9103 description translator. */
9105 /* The following macro value is suffix of name of description file of
9106 pipeline hazards description translator. */
9107 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9109 /* The function returns suffix of given file name. The returned
9110 string can not be changed. */
9111 static const char *
9112 file_name_suffix (const char *file_name)
9114 const char *last_period;
9116 for (last_period = NULL; *file_name != '\0'; file_name++)
9117 if (*file_name == '.')
9118 last_period = file_name;
9119 return (last_period == NULL ? file_name : last_period);
9122 /* The function returns base name of given file name, i.e. pointer to
9123 first char after last `/' (or `\' for WIN32) in given file name,
9124 given file name itself if the directory name is absent. The
9125 returned string can not be changed. */
9126 static const char *
9127 base_file_name (const char *file_name)
9129 int directory_name_length;
9131 directory_name_length = strlen (file_name);
9132 #ifdef WIN32
9133 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9134 && file_name[directory_name_length] != '\\')
9135 #else
9136 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9137 #endif
9138 directory_name_length--;
9139 return file_name + directory_name_length + 1;
9142 /* The following is top level function to initialize the work of
9143 pipeline hazards description translator. */
9144 static void
9145 initiate_automaton_gen (int argc, char **argv)
9147 const char *base_name;
9148 int i;
9150 ndfa_flag = 0;
9151 split_argument = 0; /* default value */
9152 no_minimization_flag = 0;
9153 time_flag = 0;
9154 stats_flag = 0;
9155 v_flag = 0;
9156 w_flag = 0;
9157 progress_flag = 0;
9158 for (i = 2; i < argc; i++)
9159 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9160 no_minimization_flag = 1;
9161 else if (strcmp (argv [i], TIME_OPTION) == 0)
9162 time_flag = 1;
9163 else if (strcmp (argv [i], STATS_OPTION) == 0)
9164 stats_flag = 1;
9165 else if (strcmp (argv [i], V_OPTION) == 0)
9166 v_flag = 1;
9167 else if (strcmp (argv [i], W_OPTION) == 0)
9168 w_flag = 1;
9169 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9170 ndfa_flag = 1;
9171 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9172 progress_flag = 1;
9173 else if (strcmp (argv [i], "-split") == 0)
9175 if (i + 1 >= argc)
9176 fatal ("-split has no argument.");
9177 fatal ("option `-split' has not been implemented yet\n");
9178 /* split_argument = atoi (argument_vect [i + 1]); */
9181 /* Initialize IR storage. */
9182 obstack_init (&irp);
9183 initiate_automaton_decl_table ();
9184 initiate_insn_decl_table ();
9185 initiate_decl_table ();
9186 output_file = stdout;
9187 output_description_file = NULL;
9188 base_name = base_file_name (argv[1]);
9189 obstack_grow (&irp, base_name,
9190 strlen (base_name) - strlen (file_name_suffix (base_name)));
9191 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9192 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9193 obstack_1grow (&irp, '\0');
9194 output_description_file_name = obstack_base (&irp);
9195 obstack_finish (&irp);
9198 /* The following function checks existence at least one arc marked by
9199 each insn. */
9200 static void
9201 check_automata_insn_issues (void)
9203 automaton_t automaton;
9204 ainsn_t ainsn, reserv_ainsn;
9206 for (automaton = description->first_automaton;
9207 automaton != NULL;
9208 automaton = automaton->next_automaton)
9210 for (ainsn = automaton->ainsn_list;
9211 ainsn != NULL;
9212 ainsn = ainsn->next_ainsn)
9213 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9215 for (reserv_ainsn = ainsn;
9216 reserv_ainsn != NULL;
9217 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9218 if (automaton->corresponding_automaton_decl != NULL)
9220 if (!w_flag)
9221 error ("Automaton `%s': Insn `%s' will never be issued",
9222 automaton->corresponding_automaton_decl->name,
9223 reserv_ainsn->insn_reserv_decl->name);
9224 else
9225 warning ("Automaton `%s': Insn `%s' will never be issued",
9226 automaton->corresponding_automaton_decl->name,
9227 reserv_ainsn->insn_reserv_decl->name);
9229 else
9231 if (!w_flag)
9232 error ("Insn `%s' will never be issued",
9233 reserv_ainsn->insn_reserv_decl->name);
9234 else
9235 warning ("Insn `%s' will never be issued",
9236 reserv_ainsn->insn_reserv_decl->name);
9242 /* The following vla is used for storing pointers to all achieved
9243 states. */
9244 static VEC(state_t, heap) *automaton_states;
9246 /* This function is called by function pass_states to add an achieved
9247 STATE. */
9248 static void
9249 add_automaton_state (state_t state)
9251 VEC_safe_push (state_t, heap, automaton_states, state);
9254 /* The following function forms list of important automata (whose
9255 states may be changed after the insn issue) for each insn. */
9256 static void
9257 form_important_insn_automata_lists (void)
9259 automaton_t automaton;
9260 decl_t decl;
9261 ainsn_t ainsn;
9262 arc_t arc;
9263 int i;
9264 size_t n;
9266 automaton_states = 0;
9267 /* Mark important ainsns. */
9268 for (automaton = description->first_automaton;
9269 automaton != NULL;
9270 automaton = automaton->next_automaton)
9272 VEC_truncate (state_t, automaton_states, 0);
9273 pass_states (automaton, add_automaton_state);
9274 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9276 state_t s = VEC_index (state_t, automaton_states, n);
9277 for (arc = first_out_arc (s);
9278 arc != NULL;
9279 arc = next_out_arc (arc))
9280 if (arc->to_state != s)
9282 gcc_assert (arc->insn->first_insn_with_same_reservs);
9283 for (ainsn = arc->insn;
9284 ainsn != NULL;
9285 ainsn = ainsn->next_same_reservs_insn)
9286 ainsn->important_p = TRUE;
9290 VEC_free (state_t, heap, automaton_states);
9292 /* Create automata sets for the insns. */
9293 for (i = 0; i < description->decls_num; i++)
9295 decl = description->decls [i];
9296 if (decl->mode == dm_insn_reserv)
9298 automata_list_start ();
9299 for (automaton = description->first_automaton;
9300 automaton != NULL;
9301 automaton = automaton->next_automaton)
9302 for (ainsn = automaton->ainsn_list;
9303 ainsn != NULL;
9304 ainsn = ainsn->next_ainsn)
9305 if (ainsn->important_p
9306 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9308 automata_list_add (automaton);
9309 break;
9311 DECL_INSN_RESERV (decl)->important_automata_list
9312 = automata_list_finish ();
9318 /* The following is top level function to generate automat(a,on) for
9319 fast recognition of pipeline hazards. */
9320 static void
9321 expand_automata (void)
9323 int i;
9325 description = XCREATENODEVAR (struct description,
9326 sizeof (struct description)
9327 /* One entry for cycle advancing insn. */
9328 + sizeof (decl_t) * VEC_length (decl_t, decls));
9329 description->decls_num = VEC_length (decl_t, decls);
9330 description->query_units_num = 0;
9331 for (i = 0; i < description->decls_num; i++)
9333 description->decls [i] = VEC_index (decl_t, decls, i);
9334 if (description->decls [i]->mode == dm_unit
9335 && DECL_UNIT (description->decls [i])->query_p)
9336 DECL_UNIT (description->decls [i])->query_num
9337 = description->query_units_num++;
9339 all_time = create_ticker ();
9340 check_time = create_ticker ();
9341 if (progress_flag)
9342 fprintf (stderr, "Check description...");
9343 check_all_description ();
9344 if (progress_flag)
9345 fprintf (stderr, "done\n");
9346 ticker_off (&check_time);
9347 generation_time = create_ticker ();
9348 if (!have_error)
9350 transform_insn_regexps ();
9351 check_unit_distributions_to_automata ();
9353 if (!have_error)
9355 generate ();
9356 check_automata_insn_issues ();
9358 if (!have_error)
9360 form_important_insn_automata_lists ();
9362 ticker_off (&generation_time);
9365 /* The following is top level function to output PHR and to finish
9366 work with pipeline description translator. */
9367 static void
9368 write_automata (void)
9370 output_time = create_ticker ();
9371 if (progress_flag)
9372 fprintf (stderr, "Forming and outputting automata tables...");
9373 output_tables ();
9374 if (progress_flag)
9376 fprintf (stderr, "done\n");
9377 fprintf (stderr, "Output functions to work with automata...");
9379 output_chip_definitions ();
9380 output_max_insn_queue_index_def ();
9381 output_internal_min_issue_delay_func ();
9382 output_internal_trans_func ();
9383 /* Cache of insn dfa codes: */
9384 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9385 fprintf (output_file, "\nstatic int %s;\n\n",
9386 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9387 output_dfa_insn_code_func ();
9388 output_trans_func ();
9389 output_min_issue_delay_func ();
9390 output_internal_dead_lock_func ();
9391 output_dead_lock_func ();
9392 output_size_func ();
9393 output_internal_reset_func ();
9394 output_reset_func ();
9395 output_min_insn_conflict_delay_func ();
9396 output_default_latencies ();
9397 output_internal_insn_latency_func ();
9398 output_insn_latency_func ();
9399 output_internal_maximal_insn_latency_func ();
9400 output_maximal_insn_latency_func ();
9401 output_print_reservation_func ();
9402 /* Output function get_cpu_unit_code. */
9403 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9404 output_get_cpu_unit_code_func ();
9405 output_cpu_unit_reservation_p ();
9406 output_insn_has_dfa_reservation_p ();
9407 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9408 CPU_UNITS_QUERY_MACRO_NAME);
9409 output_dfa_clean_insn_cache_func ();
9410 output_dfa_start_func ();
9411 output_dfa_finish_func ();
9412 if (progress_flag)
9413 fprintf (stderr, "done\n");
9414 if (v_flag)
9416 output_description_file = fopen (output_description_file_name, "w");
9417 if (output_description_file == NULL)
9419 perror (output_description_file_name);
9420 exit (FATAL_EXIT_CODE);
9422 if (progress_flag)
9423 fprintf (stderr, "Output automata description...");
9424 output_description ();
9425 output_automaton_descriptions ();
9426 if (progress_flag)
9427 fprintf (stderr, "done\n");
9428 output_statistics (output_description_file);
9430 if (stats_flag)
9431 output_statistics (stderr);
9432 ticker_off (&output_time);
9433 if (time_flag)
9434 output_time_statistics (stderr);
9435 finish_states ();
9436 finish_arcs ();
9437 finish_automata_lists ();
9438 if (time_flag)
9440 fprintf (stderr, "Summary:\n");
9441 fprintf (stderr, " check time ");
9442 print_active_time (stderr, check_time);
9443 fprintf (stderr, ", generation time ");
9444 print_active_time (stderr, generation_time);
9445 fprintf (stderr, ", all time ");
9446 print_active_time (stderr, all_time);
9447 fprintf (stderr, "\n");
9449 /* Finish all work. */
9450 if (output_description_file != NULL)
9452 fflush (output_description_file);
9453 if (ferror (stdout) != 0)
9454 fatal ("Error in writing DFA description file %s: %s",
9455 output_description_file_name, xstrerror (errno));
9456 fclose (output_description_file);
9458 finish_automaton_decl_table ();
9459 finish_insn_decl_table ();
9460 finish_decl_table ();
9461 obstack_free (&irp, NULL);
9462 if (have_error && output_description_file != NULL)
9463 remove (output_description_file_name);
9467 main (int argc, char **argv)
9469 rtx desc;
9471 progname = "genautomata";
9473 if (!init_rtx_reader_args (argc, argv))
9474 return (FATAL_EXIT_CODE);
9476 initiate_automaton_gen (argc, argv);
9477 while (1)
9479 int lineno;
9480 int insn_code_number;
9482 desc = read_md_rtx (&lineno, &insn_code_number);
9483 if (desc == NULL)
9484 break;
9486 switch (GET_CODE (desc))
9488 case DEFINE_CPU_UNIT:
9489 gen_cpu_unit (desc);
9490 break;
9492 case DEFINE_QUERY_CPU_UNIT:
9493 gen_query_cpu_unit (desc);
9494 break;
9496 case DEFINE_BYPASS:
9497 gen_bypass (desc);
9498 break;
9500 case EXCLUSION_SET:
9501 gen_excl_set (desc);
9502 break;
9504 case PRESENCE_SET:
9505 gen_presence_set (desc);
9506 break;
9508 case FINAL_PRESENCE_SET:
9509 gen_final_presence_set (desc);
9510 break;
9512 case ABSENCE_SET:
9513 gen_absence_set (desc);
9514 break;
9516 case FINAL_ABSENCE_SET:
9517 gen_final_absence_set (desc);
9518 break;
9520 case DEFINE_AUTOMATON:
9521 gen_automaton (desc);
9522 break;
9524 case AUTOMATA_OPTION:
9525 gen_automata_option (desc);
9526 break;
9528 case DEFINE_RESERVATION:
9529 gen_reserv (desc);
9530 break;
9532 case DEFINE_INSN_RESERVATION:
9533 gen_insn_reserv (desc);
9534 break;
9536 default:
9537 break;
9541 if (have_error)
9542 return FATAL_EXIT_CODE;
9544 if (VEC_length (decl_t, decls) > 0)
9546 expand_automata ();
9547 if (!have_error)
9549 puts ("/* Generated automatically by the program `genautomata'\n"
9550 " from the machine description file `md'. */\n\n"
9551 "#include \"config.h\"\n"
9552 "#include \"system.h\"\n"
9553 "#include \"coretypes.h\"\n"
9554 "#include \"tm.h\"\n"
9555 "#include \"rtl.h\"\n"
9556 "#include \"tm_p.h\"\n"
9557 "#include \"insn-config.h\"\n"
9558 "#include \"recog.h\"\n"
9559 "#include \"regs.h\"\n"
9560 "#include \"output.h\"\n"
9561 "#include \"insn-attr.h\"\n"
9562 "#include \"diagnostic-core.h\"\n"
9563 "#include \"flags.h\"\n"
9564 "#include \"function.h\"\n"
9565 "#include \"emit-rtl.h\"\n");
9566 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9568 write_automata ();
9571 else
9573 puts ("/* Generated automatically by the program `genautomata'\n"
9574 " from the machine description file `md'. */\n\n"
9575 "/* There is no automaton, but ISO C forbids empty\n"
9576 " translation units, so include a header file with some\n"
9577 " declarations, and its pre-requisite header file. */\n"
9578 "#include \"config.h\"\n"
9579 "#include \"system.h\"\n");
9582 fflush (stdout);
9583 return (ferror (stdout) != 0 || have_error
9584 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);