* config/xtensa/elf.h (HANDLE_PRAGMA_PACK_PUSH_POP): Define.
[official-gcc.git] / gcc / genautomata.c
blobfd8edebcea84644be6231b21526d513a5295bb4c
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
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 2, 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 COPYING. If not, write to the Free
21 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
22 02110-1301, USA. */
24 /* References:
26 1. Detecting pipeline structural hazards quickly. T. Proebsting,
27 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
28 Principles of Programming Languages, pages 280--286, 1994.
30 This article is a good start point to understand usage of finite
31 state automata for pipeline hazard recognizers. But I'd
32 recommend the 2nd article for more deep understanding.
34 2. Efficient Instruction Scheduling Using Finite State Automata:
35 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
36 article about usage of finite state automata for pipeline hazard
37 recognizers.
39 The current implementation is different from the 2nd article in the
40 following:
42 1. New operator `|' (alternative) is permitted in functional unit
43 reservation which can be treated deterministically and
44 non-deterministically.
46 2. Possibility of usage of nondeterministic automata too.
48 3. Possibility to query functional unit reservations for given
49 automaton state.
51 4. Several constructions to describe impossible reservations
52 (`exclusion_set', `presence_set', `final_presence_set',
53 `absence_set', and `final_absence_set').
55 5. No reverse automata are generated. Trace instruction scheduling
56 requires this. It can be easily added in the future if we
57 really need this.
59 6. Union of automaton states are not generated yet. It is planned
60 to be implemented. Such feature is needed to make more accurate
61 interlock insn scheduling to get state describing functional
62 unit reservation in a joint CFG point. */
64 /* This file code processes constructions of machine description file
65 which describes automaton used for recognition of processor pipeline
66 hazards by insn scheduler and can be used for other tasks (such as
67 VLIW insn packing.
69 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
70 `gen_bypass', `gen_excl_set', `gen_presence_set',
71 `gen_final_presence_set', `gen_absence_set',
72 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
73 `gen_reserv', `gen_insn_reserv' are called from file
74 `genattrtab.c'. They transform RTL constructions describing
75 automata in .md file into internal representation convenient for
76 further processing.
78 The translator major function `expand_automata' processes the
79 description internal representation into finite state automaton.
80 It can be divided on:
82 o checking correctness of the automaton pipeline description
83 (major function is `check_all_description').
85 o generating automaton (automata) from the description (major
86 function is `make_automaton').
88 o optional transformation of nondeterministic finite state
89 automata into deterministic ones if the alternative operator
90 `|' is treated nondeterministically in the description (major
91 function is NDFA_to_DFA).
93 o optional minimization of the finite state automata by merging
94 equivalent automaton states (major function is `minimize_DFA').
96 o forming tables (some as comb vectors) and attributes
97 representing the automata (functions output_..._table).
99 Function `write_automata' outputs the created finite state
100 automaton as different tables and functions which works with the
101 automata to inquire automaton state and to change its state. These
102 function are used by gcc instruction scheduler and may be some
103 other gcc code. */
105 #include "bconfig.h"
106 #include "system.h"
107 #include "coretypes.h"
108 #include "tm.h"
109 #include "rtl.h"
110 #include "obstack.h"
111 #include "errors.h"
112 #include "gensupport.h"
114 #include <math.h>
115 #include "hashtab.h"
116 #include "vec.h"
118 #ifndef CHAR_BIT
119 #define CHAR_BIT 8
120 #endif
122 /* Positions in machine description file. Now they are not used. But
123 they could be used in the future for better diagnostic messages. */
124 typedef int pos_t;
126 /* The following is element of vector of current (and planned in the
127 future) functional unit reservations. */
128 typedef unsigned HOST_WIDE_INT set_el_t;
130 /* Reservations of function units are represented by value of the following
131 type. */
132 typedef set_el_t *reserv_sets_t;
134 /* The following structure describes a ticker. */
135 struct ticker
137 /* The following member value is time of the ticker creation with
138 taking into account time when the ticker is off. Active time of
139 the ticker is current time minus the value. */
140 int modified_creation_time;
141 /* The following member value is time (incremented by one) when the
142 ticker was off. Zero value means that now the ticker is on. */
143 int incremented_off_time;
146 /* The ticker is represented by the following type. */
147 typedef struct ticker ticker_t;
149 /* The following type describes elements of output vectors. */
150 typedef HOST_WIDE_INT vect_el_t;
152 /* Forward declaration of structures of internal representation of
153 pipeline description based on NDFA. */
155 struct unit_decl;
156 struct bypass_decl;
157 struct result_decl;
158 struct automaton_decl;
159 struct unit_pattern_rel_decl;
160 struct reserv_decl;
161 struct insn_reserv_decl;
162 struct decl;
163 struct unit_regexp;
164 struct result_regexp;
165 struct reserv_regexp;
166 struct nothing_regexp;
167 struct sequence_regexp;
168 struct repeat_regexp;
169 struct allof_regexp;
170 struct oneof_regexp;
171 struct regexp;
172 struct description;
173 struct unit_set_el;
174 struct pattern_set_el;
175 struct pattern_reserv;
176 struct state;
177 struct alt_state;
178 struct arc;
179 struct ainsn;
180 struct automaton;
181 struct state_ainsn_table;
183 /* The following typedefs are for brevity. */
184 typedef struct unit_decl *unit_decl_t;
185 typedef struct decl *decl_t;
186 typedef struct regexp *regexp_t;
187 typedef struct unit_set_el *unit_set_el_t;
188 typedef struct pattern_set_el *pattern_set_el_t;
189 typedef struct pattern_reserv *pattern_reserv_t;
190 typedef struct alt_state *alt_state_t;
191 typedef struct state *state_t;
192 typedef struct arc *arc_t;
193 typedef struct ainsn *ainsn_t;
194 typedef struct automaton *automaton_t;
195 typedef struct automata_list_el *automata_list_el_t;
196 typedef struct state_ainsn_table *state_ainsn_table_t;
198 /* Undefined position. */
199 static pos_t no_pos = 0;
201 /* All IR is stored in the following obstack. */
202 static struct obstack irp;
205 /* Declare vector types for various data structures: */
207 DEF_VEC_P(alt_state_t);
208 DEF_VEC_ALLOC_P(alt_state_t,heap);
209 DEF_VEC_P(ainsn_t);
210 DEF_VEC_ALLOC_P(ainsn_t,heap);
211 DEF_VEC_P(state_t);
212 DEF_VEC_ALLOC_P(state_t,heap);
213 DEF_VEC_P(decl_t);
214 DEF_VEC_ALLOC_P(decl_t,heap);
215 DEF_VEC_P(reserv_sets_t);
216 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
218 DEF_VEC_I(vect_el_t);
219 DEF_VEC_ALLOC_I(vect_el_t, heap);
220 typedef VEC(vect_el_t,heap) *vla_hwint_t;
222 /* Forward declarations of functions used before their definitions, only. */
223 static regexp_t gen_regexp_sequence (const char *);
224 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
225 reserv_sets_t);
226 static reserv_sets_t get_excl_set (reserv_sets_t);
227 static int check_presence_pattern_sets (reserv_sets_t,
228 reserv_sets_t, int);
229 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
230 int);
231 static arc_t first_out_arc (state_t);
232 static arc_t next_out_arc (arc_t);
236 /* Options with the following names can be set up in automata_option
237 construction. Because the strings occur more one time we use the
238 macros. */
240 #define NO_MINIMIZATION_OPTION "-no-minimization"
242 #define TIME_OPTION "-time"
244 #define V_OPTION "-v"
246 #define W_OPTION "-w"
248 #define NDFA_OPTION "-ndfa"
250 #define PROGRESS_OPTION "-progress"
252 /* The following flags are set up by function `initiate_automaton_gen'. */
254 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
255 static int ndfa_flag;
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag;
260 /* Value of this variable is number of automata being generated. The
261 actual number of automata may be less this value if there is not
262 sufficient number of units. This value is defined by argument of
263 option `-split' or by constructions automaton if the value is zero
264 (it is default value of the argument). */
265 static int split_argument;
267 /* Flag of output time statistics (`-time'). */
268 static int time_flag;
270 /* Flag of creation of description file which contains description of
271 result automaton and statistics information (`-v'). */
272 static int v_flag;
274 /* Flag of output of a progress bar showing how many states were
275 generated so far for automaton being processed (`-progress'). */
276 static int progress_flag;
278 /* Flag of generating warning instead of error for non-critical errors
279 (`-w'). */
280 static int w_flag;
283 /* Output file for pipeline hazard recognizer (PHR) being generated.
284 The value is NULL if the file is not defined. */
285 static FILE *output_file;
287 /* Description file of PHR. The value is NULL if the file is not
288 created. */
289 static FILE *output_description_file;
291 /* PHR description file name. */
292 static char *output_description_file_name;
294 /* Value of the following variable is node representing description
295 being processed. This is start point of IR. */
296 static struct description *description;
300 /* This page contains description of IR structure (nodes). */
302 enum decl_mode
304 dm_unit,
305 dm_bypass,
306 dm_automaton,
307 dm_excl,
308 dm_presence,
309 dm_absence,
310 dm_reserv,
311 dm_insn_reserv
314 /* This describes define_cpu_unit and define_query_cpu_unit (see file
315 rtl.def). */
316 struct unit_decl
318 const char *name;
319 /* NULL if the automaton name is absent. */
320 const char *automaton_name;
321 /* If the following value is not zero, the cpu unit reservation is
322 described in define_query_cpu_unit. */
323 char query_p;
325 /* The following fields are defined by checker. */
327 /* The following field value is nonzero if the unit is used in an
328 regexp. */
329 char unit_is_used;
331 /* The following field value is order number (0, 1, ...) of given
332 unit. */
333 int unit_num;
334 /* The following field value is corresponding declaration of
335 automaton which was given in description. If the field value is
336 NULL then automaton in the unit declaration was absent. */
337 struct automaton_decl *automaton_decl;
338 /* The following field value is maximal cycle number (1, ...) on
339 which given unit occurs in insns. Zero value means that given
340 unit is not used in insns. */
341 int max_occ_cycle_num;
342 /* The following field value is minimal cycle number (0, ...) on
343 which given unit occurs in insns. -1 value means that given
344 unit is not used in insns. */
345 int min_occ_cycle_num;
346 /* The following list contains units which conflict with given
347 unit. */
348 unit_set_el_t excl_list;
349 /* The following list contains patterns which are required to
350 reservation of given unit. */
351 pattern_set_el_t presence_list;
352 pattern_set_el_t final_presence_list;
353 /* The following list contains patterns which should be not present
354 in reservation for given unit. */
355 pattern_set_el_t absence_list;
356 pattern_set_el_t final_absence_list;
357 /* The following is used only when `query_p' has nonzero value.
358 This is query number for the unit. */
359 int query_num;
360 /* The following is the last cycle on which the unit was checked for
361 correct distributions of units to automata in a regexp. */
362 int last_distribution_check_cycle;
364 /* The following fields are defined by automaton generator. */
366 /* The following field value is number of the automaton to which
367 given unit belongs. */
368 int corresponding_automaton_num;
369 /* If the following value is not zero, the cpu unit is present in a
370 `exclusion_set' or in right part of a `presence_set',
371 `final_presence_set', `absence_set', and
372 `final_absence_set'define_query_cpu_unit. */
373 char in_set_p;
376 /* This describes define_bypass (see file rtl.def). */
377 struct bypass_decl
379 int latency;
380 const char *out_insn_name;
381 const char *in_insn_name;
382 const char *bypass_guard_name;
384 /* The following fields are defined by checker. */
386 /* output and input insns of given bypass. */
387 struct insn_reserv_decl *out_insn_reserv;
388 struct insn_reserv_decl *in_insn_reserv;
389 /* The next bypass for given output insn. */
390 struct bypass_decl *next;
393 /* This describes define_automaton (see file rtl.def). */
394 struct automaton_decl
396 const char *name;
398 /* The following fields are defined by automaton generator. */
400 /* The following field value is nonzero if the automaton is used in
401 an regexp definition. */
402 char automaton_is_used;
404 /* The following fields are defined by checker. */
406 /* The following field value is the corresponding automaton. This
407 field is not NULL only if the automaton is present in unit
408 declarations and the automatic partition on automata is not
409 used. */
410 automaton_t corresponding_automaton;
413 /* This describes exclusion relations: exclusion_set (see file
414 rtl.def). */
415 struct excl_rel_decl
417 int all_names_num;
418 int first_list_length;
419 char *names [1];
422 /* This describes unit relations: [final_]presence_set or
423 [final_]absence_set (see file rtl.def). */
424 struct unit_pattern_rel_decl
426 int final_p;
427 int names_num;
428 int patterns_num;
429 char **names;
430 char ***patterns;
433 /* This describes define_reservation (see file rtl.def). */
434 struct reserv_decl
436 const char *name;
437 regexp_t regexp;
439 /* The following fields are defined by checker. */
441 /* The following field value is nonzero if the unit is used in an
442 regexp. */
443 char reserv_is_used;
444 /* The following field is used to check up cycle in expression
445 definition. */
446 int loop_pass_num;
449 /* This describes define_insn_reservation (see file rtl.def). */
450 struct insn_reserv_decl
452 rtx condexp;
453 int default_latency;
454 regexp_t regexp;
455 const char *name;
457 /* The following fields are defined by checker. */
459 /* The following field value is order number (0, 1, ...) of given
460 insn. */
461 int insn_num;
462 /* The following field value is list of bypasses in which given insn
463 is output insn. */
464 struct bypass_decl *bypass_list;
466 /* The following fields are defined by automaton generator. */
468 /* The following field is the insn regexp transformed that
469 the regexp has not optional regexp, repetition regexp, and an
470 reservation name (i.e. reservation identifiers are changed by the
471 corresponding regexp) and all alternations are the topest level
472 of the regexp. The value can be NULL only if it is special
473 insn `cycle advancing'. */
474 regexp_t transformed_regexp;
475 /* The following field value is list of arcs marked given
476 insn. The field is used in transformation NDFA -> DFA. */
477 arc_t arcs_marked_by_insn;
478 /* The two following fields are used during minimization of a finite state
479 automaton. */
480 /* The field value is number of equivalence class of state into
481 which arc marked by given insn enters from a state (fixed during
482 an automaton minimization). */
483 int equiv_class_num;
484 /* The following member value is the list to automata which can be
485 changed by the insn issue. */
486 automata_list_el_t important_automata_list;
487 /* The following member is used to process insn once for output. */
488 int processed_p;
491 /* This contains a declaration mentioned above. */
492 struct decl
494 /* What node in the union? */
495 enum decl_mode mode;
496 pos_t pos;
497 union
499 struct unit_decl unit;
500 struct bypass_decl bypass;
501 struct automaton_decl automaton;
502 struct excl_rel_decl excl;
503 struct unit_pattern_rel_decl presence;
504 struct unit_pattern_rel_decl absence;
505 struct reserv_decl reserv;
506 struct insn_reserv_decl insn_reserv;
507 } decl;
510 /* The following structures represent parsed reservation strings. */
511 enum regexp_mode
513 rm_unit,
514 rm_reserv,
515 rm_nothing,
516 rm_sequence,
517 rm_repeat,
518 rm_allof,
519 rm_oneof
522 /* Cpu unit in reservation. */
523 struct unit_regexp
525 const char *name;
526 unit_decl_t unit_decl;
529 /* Define_reservation in a reservation. */
530 struct reserv_regexp
532 const char *name;
533 struct reserv_decl *reserv_decl;
536 /* Absence of reservation (represented by string `nothing'). */
537 struct nothing_regexp
539 /* This used to be empty but ISO C doesn't allow that. */
540 char unused;
543 /* Representation of reservations separated by ',' (see file
544 rtl.def). */
545 struct sequence_regexp
547 int regexps_num;
548 regexp_t regexps [1];
551 /* Representation of construction `repeat' (see file rtl.def). */
552 struct repeat_regexp
554 int repeat_num;
555 regexp_t regexp;
558 /* Representation of reservations separated by '+' (see file
559 rtl.def). */
560 struct allof_regexp
562 int regexps_num;
563 regexp_t regexps [1];
566 /* Representation of reservations separated by '|' (see file
567 rtl.def). */
568 struct oneof_regexp
570 int regexps_num;
571 regexp_t regexps [1];
574 /* Representation of a reservation string. */
575 struct regexp
577 /* What node in the union? */
578 enum regexp_mode mode;
579 pos_t pos;
580 union
582 struct unit_regexp unit;
583 struct reserv_regexp reserv;
584 struct nothing_regexp nothing;
585 struct sequence_regexp sequence;
586 struct repeat_regexp repeat;
587 struct allof_regexp allof;
588 struct oneof_regexp oneof;
589 } regexp;
592 /* Represents description of pipeline hazard description based on
593 NDFA. */
594 struct description
596 int decls_num;
598 /* The following fields are defined by checker. */
600 /* The following fields values are correspondingly number of all
601 units, query units, and insns in the description. */
602 int units_num;
603 int query_units_num;
604 int insns_num;
605 /* The following field value is max length (in cycles) of
606 reservations of insns. The field value is defined only for
607 correct programs. */
608 int max_insn_reserv_cycles;
610 /* The following fields are defined by automaton generator. */
612 /* The following field value is the first automaton. */
613 automaton_t first_automaton;
615 /* The following field is created by pipeline hazard parser and
616 contains all declarations. We allocate additional entry for
617 special insn "cycle advancing" which is added by the automaton
618 generator. */
619 decl_t decls [1];
623 /* The following nodes are created in automaton checker. */
625 /* The following nodes represent exclusion set for cpu units. Each
626 element is accessed through only one excl_list. */
627 struct unit_set_el
629 unit_decl_t unit_decl;
630 unit_set_el_t next_unit_set_el;
633 /* The following nodes represent presence or absence pattern for cpu
634 units. Each element is accessed through only one presence_list or
635 absence_list. */
636 struct pattern_set_el
638 /* The number of units in unit_decls. */
639 int units_num;
640 /* The units forming the pattern. */
641 struct unit_decl **unit_decls;
642 pattern_set_el_t next_pattern_set_el;
646 /* The following nodes are created in automaton generator. */
649 /* The following nodes represent presence or absence pattern for cpu
650 units. Each element is accessed through only one element of
651 unit_presence_set_table or unit_absence_set_table. */
652 struct pattern_reserv
654 reserv_sets_t reserv;
655 pattern_reserv_t next_pattern_reserv;
658 /* The following node type describes state automaton. The state may
659 be deterministic or non-deterministic. Non-deterministic state has
660 several component states which represent alternative cpu units
661 reservations. The state also is used for describing a
662 deterministic reservation of automaton insn. */
663 struct state
665 /* The following member value is nonzero if there is a transition by
666 cycle advancing. */
667 int new_cycle_p;
668 /* The following field is list of processor unit reservations on
669 each cycle. */
670 reserv_sets_t reservs;
671 /* The following field is unique number of given state between other
672 states. */
673 int unique_num;
674 /* The following field value is automaton to which given state
675 belongs. */
676 automaton_t automaton;
677 /* The following field value is the first arc output from given
678 state. */
679 arc_t first_out_arc;
680 unsigned int num_out_arcs;
681 /* The following field is used to form NDFA. */
682 char it_was_placed_in_stack_for_NDFA_forming;
683 /* The following field is used to form DFA. */
684 char it_was_placed_in_stack_for_DFA_forming;
685 /* The following field is used to transform NDFA to DFA and DFA
686 minimization. The field value is not NULL if the state is a
687 compound state. In this case the value of field `unit_sets_list'
688 is NULL. All states in the list are in the hash table. The list
689 is formed through field `next_sorted_alt_state'. We should
690 support only one level of nesting state. */
691 alt_state_t component_states;
692 /* The following field is used for passing graph of states. */
693 int pass_num;
694 /* The list of states belonging to one equivalence class is formed
695 with the aid of the following field. */
696 state_t next_equiv_class_state;
697 /* The two following fields are used during minimization of a finite
698 state automaton. */
699 int equiv_class_num_1, equiv_class_num_2;
700 /* The following field is used during minimization of a finite state
701 automaton. The field value is state corresponding to equivalence
702 class to which given state belongs. */
703 state_t equiv_class_state;
704 unsigned int *presence_signature;
705 /* The following field value is the order number of given state.
706 The states in final DFA is enumerated with the aid of the
707 following field. */
708 int order_state_num;
709 /* This member is used for passing states for searching minimal
710 delay time. */
711 int state_pass_num;
712 /* The following member is used to evaluate min issue delay of insn
713 for a state. */
714 int min_insn_issue_delay;
715 /* The following member is used to evaluate max issue rate of the
716 processor. The value of the member is maximal length of the path
717 from given state no containing arcs marked by special insn `cycle
718 advancing'. */
719 int longest_path_length;
722 /* The following macro is an initial value of member
723 `longest_path_length' of a state. */
724 #define UNDEFINED_LONGEST_PATH_LENGTH -1
726 /* Automaton arc. */
727 struct arc
729 /* The following field refers for the state into which given arc
730 enters. */
731 state_t to_state;
732 /* The following field describes that the insn issue (with cycle
733 advancing for special insn `cycle advancing' and without cycle
734 advancing for others) makes transition from given state to
735 another given state. */
736 ainsn_t insn;
737 /* The following field value is the next arc output from the same
738 state. */
739 arc_t next_out_arc;
740 /* List of arcs marked given insn is formed with the following
741 field. The field is used in transformation NDFA -> DFA. */
742 arc_t next_arc_marked_by_insn;
745 /* The following node type describes a deterministic alternative in
746 non-deterministic state which characterizes cpu unit reservations
747 of automaton insn or which is part of NDFA. */
748 struct alt_state
750 /* The following field is a deterministic state which characterizes
751 unit reservations of the instruction. */
752 state_t state;
753 /* The following field refers to the next state which characterizes
754 unit reservations of the instruction. */
755 alt_state_t next_alt_state;
756 /* The following field refers to the next state in sorted list. */
757 alt_state_t next_sorted_alt_state;
760 /* The following node type describes insn of automaton. They are
761 labels of FA arcs. */
762 struct ainsn
764 /* The following field value is the corresponding insn declaration
765 of description. */
766 struct insn_reserv_decl *insn_reserv_decl;
767 /* The following field value is the next insn declaration for an
768 automaton. */
769 ainsn_t next_ainsn;
770 /* The following field is states which characterize automaton unit
771 reservations of the instruction. The value can be NULL only if it
772 is special insn `cycle advancing'. */
773 alt_state_t alt_states;
774 /* The following field is sorted list of states which characterize
775 automaton unit reservations of the instruction. The value can be
776 NULL only if it is special insn `cycle advancing'. */
777 alt_state_t sorted_alt_states;
778 /* The following field refers the next automaton insn with
779 the same reservations. */
780 ainsn_t next_same_reservs_insn;
781 /* The following field is flag of the first automaton insn with the
782 same reservations in the declaration list. Only arcs marked such
783 insn is present in the automaton. This significantly decreases
784 memory requirements especially when several automata are
785 formed. */
786 char first_insn_with_same_reservs;
787 /* The following member has nonzero value if there is arc from state of
788 the automaton marked by the ainsn. */
789 char arc_exists_p;
790 /* Cyclic list of insns of an equivalence class is formed with the
791 aid of the following field. */
792 ainsn_t next_equiv_class_insn;
793 /* The following field value is nonzero if the insn declaration is
794 the first insn declaration with given equivalence number. */
795 char first_ainsn_with_given_equivalence_num;
796 /* The following field is number of class of equivalence of insns.
797 It is necessary because many insns may be equivalent with the
798 point of view of pipeline hazards. */
799 int insn_equiv_class_num;
800 /* The following member value is TRUE if there is an arc in the
801 automaton marked by the insn into another state. In other
802 words, the insn can change the state of the automaton. */
803 int important_p;
806 /* The following describes an automaton for PHR. */
807 struct automaton
809 /* The following field value is the list of insn declarations for
810 given automaton. */
811 ainsn_t ainsn_list;
812 /* The following field value is the corresponding automaton
813 declaration. This field is not NULL only if the automatic
814 partition on automata is not used. */
815 struct automaton_decl *corresponding_automaton_decl;
816 /* The following field value is the next automaton. */
817 automaton_t next_automaton;
818 /* The following field is start state of FA. There are not unit
819 reservations in the state. */
820 state_t start_state;
821 /* The following field value is number of equivalence classes of
822 insns (see field `insn_equiv_class_num' in
823 `insn_reserv_decl'). */
824 int insn_equiv_classes_num;
825 /* The following field value is number of states of final DFA. */
826 int achieved_states_num;
827 /* The following field value is the order number (0, 1, ...) of
828 given automaton. */
829 int automaton_order_num;
830 /* The following fields contain statistics information about
831 building automaton. */
832 int NDFA_states_num, DFA_states_num;
833 /* The following field value is defined only if minimization of DFA
834 is used. */
835 int minimal_DFA_states_num;
836 int NDFA_arcs_num, DFA_arcs_num;
837 /* The following field value is defined only if minimization of DFA
838 is used. */
839 int minimal_DFA_arcs_num;
840 /* The following member refers for two table state x ainsn -> int.
841 ??? Above sentence is incomprehensible. */
842 state_ainsn_table_t trans_table;
843 /* The following member value is maximal value of min issue delay
844 for insns of the automaton. */
845 int max_min_delay;
846 /* Usually min issue delay is small and we can place several (2, 4,
847 8) elements in one vector element. So the compression factor can
848 be 1 (no compression), 2, 4, 8. */
849 int min_issue_delay_table_compression_factor;
850 /* Total number of locked states in this automaton. */
851 int locked_states;
854 /* The following is the element of the list of automata. */
855 struct automata_list_el
857 /* The automaton itself. */
858 automaton_t automaton;
859 /* The next automata set element. */
860 automata_list_el_t next_automata_list_el;
863 /* The following structure describes a table state X ainsn -> int(>= 0). */
864 struct state_ainsn_table
866 /* Automaton to which given table belongs. */
867 automaton_t automaton;
868 /* The following tree vectors for comb vector implementation of the
869 table. */
870 vla_hwint_t comb_vect;
871 vla_hwint_t check_vect;
872 vla_hwint_t base_vect;
873 /* This is simple implementation of the table. */
874 vla_hwint_t full_vect;
875 /* Minimal and maximal values of the previous vectors. */
876 int min_comb_vect_el_value, max_comb_vect_el_value;
877 int min_base_vect_el_value, max_base_vect_el_value;
880 /* Macros to access members of unions. Use only them for access to
881 union members of declarations and regexps. */
883 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
885 #define DECL_UNIT(d) __extension__ \
886 (({ struct decl *const _decl = (d); \
887 if (_decl->mode != dm_unit) \
888 decl_mode_check_failed (_decl->mode, "dm_unit", \
889 __FILE__, __LINE__, __FUNCTION__); \
890 &(_decl)->decl.unit; }))
892 #define DECL_BYPASS(d) __extension__ \
893 (({ struct decl *const _decl = (d); \
894 if (_decl->mode != dm_bypass) \
895 decl_mode_check_failed (_decl->mode, "dm_bypass", \
896 __FILE__, __LINE__, __FUNCTION__); \
897 &(_decl)->decl.bypass; }))
899 #define DECL_AUTOMATON(d) __extension__ \
900 (({ struct decl *const _decl = (d); \
901 if (_decl->mode != dm_automaton) \
902 decl_mode_check_failed (_decl->mode, "dm_automaton", \
903 __FILE__, __LINE__, __FUNCTION__); \
904 &(_decl)->decl.automaton; }))
906 #define DECL_EXCL(d) __extension__ \
907 (({ struct decl *const _decl = (d); \
908 if (_decl->mode != dm_excl) \
909 decl_mode_check_failed (_decl->mode, "dm_excl", \
910 __FILE__, __LINE__, __FUNCTION__); \
911 &(_decl)->decl.excl; }))
913 #define DECL_PRESENCE(d) __extension__ \
914 (({ struct decl *const _decl = (d); \
915 if (_decl->mode != dm_presence) \
916 decl_mode_check_failed (_decl->mode, "dm_presence", \
917 __FILE__, __LINE__, __FUNCTION__); \
918 &(_decl)->decl.presence; }))
920 #define DECL_ABSENCE(d) __extension__ \
921 (({ struct decl *const _decl = (d); \
922 if (_decl->mode != dm_absence) \
923 decl_mode_check_failed (_decl->mode, "dm_absence", \
924 __FILE__, __LINE__, __FUNCTION__); \
925 &(_decl)->decl.absence; }))
927 #define DECL_RESERV(d) __extension__ \
928 (({ struct decl *const _decl = (d); \
929 if (_decl->mode != dm_reserv) \
930 decl_mode_check_failed (_decl->mode, "dm_reserv", \
931 __FILE__, __LINE__, __FUNCTION__); \
932 &(_decl)->decl.reserv; }))
934 #define DECL_INSN_RESERV(d) __extension__ \
935 (({ struct decl *const _decl = (d); \
936 if (_decl->mode != dm_insn_reserv) \
937 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
938 __FILE__, __LINE__, __FUNCTION__); \
939 &(_decl)->decl.insn_reserv; }))
941 static const char *decl_name (enum decl_mode);
942 static void decl_mode_check_failed (enum decl_mode, const char *,
943 const char *, int, const char *)
944 ATTRIBUTE_NORETURN;
946 /* Return string representation of declaration mode MODE. */
947 static const char *
948 decl_name (enum decl_mode mode)
950 static char str [100];
952 if (mode == dm_unit)
953 return "dm_unit";
954 else if (mode == dm_bypass)
955 return "dm_bypass";
956 else if (mode == dm_automaton)
957 return "dm_automaton";
958 else if (mode == dm_excl)
959 return "dm_excl";
960 else if (mode == dm_presence)
961 return "dm_presence";
962 else if (mode == dm_absence)
963 return "dm_absence";
964 else if (mode == dm_reserv)
965 return "dm_reserv";
966 else if (mode == dm_insn_reserv)
967 return "dm_insn_reserv";
968 else
969 sprintf (str, "unknown (%d)", (int) mode);
970 return str;
973 /* The function prints message about unexpected declaration and finish
974 the program. */
975 static void
976 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
977 const char *file, int line, const char *func)
979 fprintf
980 (stderr,
981 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
982 file, line, func, expected_mode_str, decl_name (mode));
983 exit (1);
987 #define REGEXP_UNIT(r) __extension__ \
988 (({ struct regexp *const _regexp = (r); \
989 if (_regexp->mode != rm_unit) \
990 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
991 __FILE__, __LINE__, __FUNCTION__); \
992 &(_regexp)->regexp.unit; }))
994 #define REGEXP_RESERV(r) __extension__ \
995 (({ struct regexp *const _regexp = (r); \
996 if (_regexp->mode != rm_reserv) \
997 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
998 __FILE__, __LINE__, __FUNCTION__); \
999 &(_regexp)->regexp.reserv; }))
1001 #define REGEXP_SEQUENCE(r) __extension__ \
1002 (({ struct regexp *const _regexp = (r); \
1003 if (_regexp->mode != rm_sequence) \
1004 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1005 __FILE__, __LINE__, __FUNCTION__); \
1006 &(_regexp)->regexp.sequence; }))
1008 #define REGEXP_REPEAT(r) __extension__ \
1009 (({ struct regexp *const _regexp = (r); \
1010 if (_regexp->mode != rm_repeat) \
1011 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1012 __FILE__, __LINE__, __FUNCTION__); \
1013 &(_regexp)->regexp.repeat; }))
1015 #define REGEXP_ALLOF(r) __extension__ \
1016 (({ struct regexp *const _regexp = (r); \
1017 if (_regexp->mode != rm_allof) \
1018 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1019 __FILE__, __LINE__, __FUNCTION__); \
1020 &(_regexp)->regexp.allof; }))
1022 #define REGEXP_ONEOF(r) __extension__ \
1023 (({ struct regexp *const _regexp = (r); \
1024 if (_regexp->mode != rm_oneof) \
1025 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1026 __FILE__, __LINE__, __FUNCTION__); \
1027 &(_regexp)->regexp.oneof; }))
1029 static const char *regexp_name (enum regexp_mode);
1030 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1031 const char *, int,
1032 const char *) ATTRIBUTE_NORETURN;
1035 /* Return string representation of regexp mode MODE. */
1036 static const char *
1037 regexp_name (enum regexp_mode mode)
1039 switch (mode)
1041 case rm_unit:
1042 return "rm_unit";
1043 case rm_reserv:
1044 return "rm_reserv";
1045 case rm_nothing:
1046 return "rm_nothing";
1047 case rm_sequence:
1048 return "rm_sequence";
1049 case rm_repeat:
1050 return "rm_repeat";
1051 case rm_allof:
1052 return "rm_allof";
1053 case rm_oneof:
1054 return "rm_oneof";
1055 default:
1056 gcc_unreachable ();
1060 /* The function prints message about unexpected regexp and finish the
1061 program. */
1062 static void
1063 regexp_mode_check_failed (enum regexp_mode mode,
1064 const char *expected_mode_str,
1065 const char *file, int line, const char *func)
1067 fprintf
1068 (stderr,
1069 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1070 file, line, func, expected_mode_str, regexp_name (mode));
1071 exit (1);
1074 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1076 #define DECL_UNIT(d) (&(d)->decl.unit)
1077 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1078 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1079 #define DECL_EXCL(d) (&(d)->decl.excl)
1080 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1081 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1082 #define DECL_RESERV(d) (&(d)->decl.reserv)
1083 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1085 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1086 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1087 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1088 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1089 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1090 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1092 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1094 /* Create IR structure (node). */
1095 static void *
1096 create_node (size_t size)
1098 void *result;
1100 obstack_blank (&irp, size);
1101 result = obstack_base (&irp);
1102 obstack_finish (&irp);
1103 /* Default values of members are NULL and zero. */
1104 memset (result, 0, size);
1105 return result;
1108 /* Copy IR structure (node). */
1109 static void *
1110 copy_node (const void *from, size_t size)
1112 void *const result = create_node (size);
1113 memcpy (result, from, size);
1114 return result;
1117 /* The function checks that NAME does not contain quotes (`"'). */
1118 static const char *
1119 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1121 const char *str;
1123 for (str = name; *str != '\0'; str++)
1124 if (*str == '\"')
1125 error ("Name `%s' contains quotes", name);
1126 return name;
1129 /* Pointers to all declarations during IR generation are stored in the
1130 following. */
1131 static VEC(decl_t,heap) *decls;
1133 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1134 string containing the next separated element, taking parentheses
1135 into account if PAR_FLAG has nonzero value. Advance the pointer to
1136 after the string scanned, or the end-of-string. Return NULL if at
1137 end of string. */
1138 static char *
1139 next_sep_el (const char **pstr, int sep, int par_flag)
1141 char *out_str;
1142 const char *p;
1143 int pars_num;
1144 int n_spaces;
1146 /* Remove leading whitespaces. */
1147 while (ISSPACE ((int) **pstr))
1148 (*pstr)++;
1150 if (**pstr == '\0')
1151 return NULL;
1153 n_spaces = 0;
1154 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1156 if (par_flag && *p == '(')
1157 pars_num++;
1158 else if (par_flag && *p == ')')
1159 pars_num--;
1160 else if (pars_num == 0 && *p == sep)
1161 break;
1162 if (pars_num == 0 && ISSPACE ((int) *p))
1163 n_spaces++;
1164 else
1166 for (; n_spaces != 0; n_spaces--)
1167 obstack_1grow (&irp, p [-n_spaces]);
1168 obstack_1grow (&irp, *p);
1171 obstack_1grow (&irp, '\0');
1172 out_str = obstack_base (&irp);
1173 obstack_finish (&irp);
1175 *pstr = p;
1176 if (**pstr == sep)
1177 (*pstr)++;
1179 return out_str;
1182 /* Given a string and a separator, return the number of separated
1183 elements in it, taking parentheses into account if PAR_FLAG has
1184 nonzero value. Return 0 for the null string, -1 if parentheses is
1185 not balanced. */
1186 static int
1187 n_sep_els (const char *s, int sep, int par_flag)
1189 int n;
1190 int pars_num;
1192 if (*s == '\0')
1193 return 0;
1195 for (pars_num = 0, n = 1; *s; s++)
1196 if (par_flag && *s == '(')
1197 pars_num++;
1198 else if (par_flag && *s == ')')
1199 pars_num--;
1200 else if (pars_num == 0 && *s == sep)
1201 n++;
1203 return (pars_num != 0 ? -1 : n);
1206 /* Given a string and a separator, return vector of strings which are
1207 elements in the string and number of elements through els_num.
1208 Take parentheses into account if PAREN_P has nonzero value. The
1209 function also inserts the end marker NULL at the end of vector.
1210 Return 0 for the null string, -1 if parentheses are not balanced. */
1211 static char **
1212 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1214 int i;
1215 char **vect;
1216 const char **pstr;
1217 char *trail;
1219 *els_num = n_sep_els (str, sep, paren_p);
1220 if (*els_num <= 0)
1221 return NULL;
1222 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1223 vect = (char **) obstack_base (&irp);
1224 obstack_finish (&irp);
1225 pstr = &str;
1226 for (i = 0; i < *els_num; i++)
1227 vect [i] = next_sep_el (pstr, sep, paren_p);
1228 trail = next_sep_el (pstr, sep, paren_p);
1229 gcc_assert (!trail);
1230 vect [i] = NULL;
1231 return vect;
1234 /* Process a DEFINE_CPU_UNIT.
1236 This gives information about a unit contained in CPU. We fill a
1237 struct unit_decl with information used later by `expand_automata'. */
1238 static void
1239 gen_cpu_unit (rtx def)
1241 decl_t decl;
1242 char **str_cpu_units;
1243 int vect_length;
1244 int i;
1246 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1247 if (str_cpu_units == NULL)
1248 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1249 for (i = 0; i < vect_length; i++)
1251 decl = create_node (sizeof (struct decl));
1252 decl->mode = dm_unit;
1253 decl->pos = 0;
1254 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1255 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1256 DECL_UNIT (decl)->query_p = 0;
1257 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1258 DECL_UNIT (decl)->in_set_p = 0;
1259 VEC_safe_push (decl_t,heap, decls, decl);
1263 /* Process a DEFINE_QUERY_CPU_UNIT.
1265 This gives information about a unit contained in CPU. We fill a
1266 struct unit_decl with information used later by `expand_automata'. */
1267 static void
1268 gen_query_cpu_unit (rtx def)
1270 decl_t decl;
1271 char **str_cpu_units;
1272 int vect_length;
1273 int i;
1275 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1276 FALSE);
1277 if (str_cpu_units == NULL)
1278 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1279 for (i = 0; i < vect_length; i++)
1281 decl = create_node (sizeof (struct decl));
1282 decl->mode = dm_unit;
1283 decl->pos = 0;
1284 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1285 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1286 DECL_UNIT (decl)->query_p = 1;
1287 VEC_safe_push (decl_t,heap, decls, decl);
1291 /* Process a DEFINE_BYPASS.
1293 This gives information about a unit contained in the CPU. We fill
1294 in a struct bypass_decl with information used later by
1295 `expand_automata'. */
1296 static void
1297 gen_bypass (rtx def)
1299 decl_t decl;
1300 char **out_insns;
1301 int out_length;
1302 char **in_insns;
1303 int in_length;
1304 int i, j;
1306 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1307 if (out_insns == NULL)
1308 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1309 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1310 if (in_insns == NULL)
1311 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1312 for (i = 0; i < out_length; i++)
1313 for (j = 0; j < in_length; j++)
1315 decl = create_node (sizeof (struct decl));
1316 decl->mode = dm_bypass;
1317 decl->pos = 0;
1318 DECL_BYPASS (decl)->latency = XINT (def, 0);
1319 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1320 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1321 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1322 VEC_safe_push (decl_t,heap, decls, decl);
1326 /* Process an EXCLUSION_SET.
1328 This gives information about a cpu unit conflicts. We fill a
1329 struct excl_rel_decl (excl) with information used later by
1330 `expand_automata'. */
1331 static void
1332 gen_excl_set (rtx def)
1334 decl_t decl;
1335 char **first_str_cpu_units;
1336 char **second_str_cpu_units;
1337 int first_vect_length;
1338 int length;
1339 int i;
1341 first_str_cpu_units
1342 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1343 if (first_str_cpu_units == NULL)
1344 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1345 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1346 FALSE);
1347 if (second_str_cpu_units == NULL)
1348 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1349 length += first_vect_length;
1350 decl = create_node (sizeof (struct decl) + (length - 1) * sizeof (char *));
1351 decl->mode = dm_excl;
1352 decl->pos = 0;
1353 DECL_EXCL (decl)->all_names_num = length;
1354 DECL_EXCL (decl)->first_list_length = first_vect_length;
1355 for (i = 0; i < length; i++)
1356 if (i < first_vect_length)
1357 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1358 else
1359 DECL_EXCL (decl)->names [i]
1360 = second_str_cpu_units [i - first_vect_length];
1361 VEC_safe_push (decl_t,heap, decls, decl);
1364 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1365 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1367 This gives information about a cpu unit reservation requirements.
1368 We fill a struct unit_pattern_rel_decl with information used later
1369 by `expand_automata'. */
1370 static void
1371 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1373 decl_t decl;
1374 char **str_cpu_units;
1375 char **str_pattern_lists;
1376 char ***str_patterns;
1377 int cpu_units_length;
1378 int length;
1379 int patterns_length;
1380 int i;
1382 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1383 FALSE);
1384 if (str_cpu_units == NULL)
1385 fatal ((presence_p
1386 ? (final_p
1387 ? "invalid first string `%s' in final_presence_set"
1388 : "invalid first string `%s' in presence_set")
1389 : (final_p
1390 ? "invalid first string `%s' in final_absence_set"
1391 : "invalid first string `%s' in absence_set")),
1392 XSTR (def, 0));
1393 str_pattern_lists = get_str_vect (XSTR (def, 1),
1394 &patterns_length, ',', FALSE);
1395 if (str_pattern_lists == NULL)
1396 fatal ((presence_p
1397 ? (final_p
1398 ? "invalid second string `%s' in final_presence_set"
1399 : "invalid second string `%s' in presence_set")
1400 : (final_p
1401 ? "invalid second string `%s' in final_absence_set"
1402 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1403 str_patterns = obstack_alloc (&irp, patterns_length * sizeof (char **));
1404 for (i = 0; i < patterns_length; i++)
1406 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1407 &length, ' ', FALSE);
1408 gcc_assert (str_patterns [i]);
1410 decl = create_node (sizeof (struct decl));
1411 decl->pos = 0;
1412 if (presence_p)
1414 decl->mode = dm_presence;
1415 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1416 DECL_PRESENCE (decl)->names = str_cpu_units;
1417 DECL_PRESENCE (decl)->patterns = str_patterns;
1418 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1419 DECL_PRESENCE (decl)->final_p = final_p;
1421 else
1423 decl->mode = dm_absence;
1424 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1425 DECL_ABSENCE (decl)->names = str_cpu_units;
1426 DECL_ABSENCE (decl)->patterns = str_patterns;
1427 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1428 DECL_ABSENCE (decl)->final_p = final_p;
1430 VEC_safe_push (decl_t,heap, decls, decl);
1433 /* Process a PRESENCE_SET.
1435 This gives information about a cpu unit reservation requirements.
1436 We fill a struct unit_pattern_rel_decl (presence) with information
1437 used later by `expand_automata'. */
1438 static void
1439 gen_presence_set (rtx def)
1441 gen_presence_absence_set (def, TRUE, FALSE);
1444 /* Process a FINAL_PRESENCE_SET.
1446 This gives information about a cpu unit reservation requirements.
1447 We fill a struct unit_pattern_rel_decl (presence) with information
1448 used later by `expand_automata'. */
1449 static void
1450 gen_final_presence_set (rtx def)
1452 gen_presence_absence_set (def, TRUE, TRUE);
1455 /* Process an ABSENCE_SET.
1457 This gives information about a cpu unit reservation requirements.
1458 We fill a struct unit_pattern_rel_decl (absence) with information
1459 used later by `expand_automata'. */
1460 static void
1461 gen_absence_set (rtx def)
1463 gen_presence_absence_set (def, FALSE, FALSE);
1466 /* Process a FINAL_ABSENCE_SET.
1468 This gives information about a cpu unit reservation requirements.
1469 We fill a struct unit_pattern_rel_decl (absence) with information
1470 used later by `expand_automata'. */
1471 static void
1472 gen_final_absence_set (rtx def)
1474 gen_presence_absence_set (def, FALSE, TRUE);
1477 /* Process a DEFINE_AUTOMATON.
1479 This gives information about a finite state automaton used for
1480 recognizing pipeline hazards. We fill a struct automaton_decl
1481 with information used later by `expand_automata'. */
1482 static void
1483 gen_automaton (rtx def)
1485 decl_t decl;
1486 char **str_automata;
1487 int vect_length;
1488 int i;
1490 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1491 if (str_automata == NULL)
1492 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1493 for (i = 0; i < vect_length; i++)
1495 decl = create_node (sizeof (struct decl));
1496 decl->mode = dm_automaton;
1497 decl->pos = 0;
1498 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1499 VEC_safe_push (decl_t,heap, decls, decl);
1503 /* Process an AUTOMATA_OPTION.
1505 This gives information how to generate finite state automaton used
1506 for recognizing pipeline hazards. */
1507 static void
1508 gen_automata_option (rtx def)
1510 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1511 no_minimization_flag = 1;
1512 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1513 time_flag = 1;
1514 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1515 v_flag = 1;
1516 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1517 w_flag = 1;
1518 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1519 ndfa_flag = 1;
1520 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1521 progress_flag = 1;
1522 else
1523 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1526 /* Name in reservation to denote absence reservation. */
1527 #define NOTHING_NAME "nothing"
1529 /* The following string contains original reservation string being
1530 parsed. */
1531 static const char *reserv_str;
1533 /* Parse an element in STR. */
1534 static regexp_t
1535 gen_regexp_el (const char *str)
1537 regexp_t regexp;
1538 char *dstr;
1539 int len;
1541 if (*str == '(')
1543 len = strlen (str);
1544 if (str [len - 1] != ')')
1545 fatal ("garbage after ) in reservation `%s'", reserv_str);
1546 dstr = alloca (len - 1);
1547 memcpy (dstr, str + 1, len - 2);
1548 dstr [len-2] = '\0';
1549 regexp = gen_regexp_sequence (dstr);
1551 else if (strcmp (str, NOTHING_NAME) == 0)
1553 regexp = create_node (sizeof (struct decl));
1554 regexp->mode = rm_nothing;
1556 else
1558 regexp = create_node (sizeof (struct decl));
1559 regexp->mode = rm_unit;
1560 REGEXP_UNIT (regexp)->name = str;
1562 return regexp;
1565 /* Parse construction `repeat' in STR. */
1566 static regexp_t
1567 gen_regexp_repeat (const char *str)
1569 regexp_t regexp;
1570 regexp_t repeat;
1571 char **repeat_vect;
1572 int els_num;
1573 int i;
1575 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1576 if (repeat_vect == NULL)
1577 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1578 if (els_num > 1)
1580 regexp = gen_regexp_el (repeat_vect [0]);
1581 for (i = 1; i < els_num; i++)
1583 repeat = create_node (sizeof (struct regexp));
1584 repeat->mode = rm_repeat;
1585 REGEXP_REPEAT (repeat)->regexp = regexp;
1586 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1587 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1588 fatal ("repetition `%s' <= 1 in reservation `%s'",
1589 str, reserv_str);
1590 regexp = repeat;
1592 return regexp;
1594 else
1595 return gen_regexp_el (str);
1598 /* Parse reservation STR which possibly contains separator '+'. */
1599 static regexp_t
1600 gen_regexp_allof (const char *str)
1602 regexp_t allof;
1603 char **allof_vect;
1604 int els_num;
1605 int i;
1607 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1608 if (allof_vect == NULL)
1609 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1610 if (els_num > 1)
1612 allof = create_node (sizeof (struct regexp)
1613 + sizeof (regexp_t) * (els_num - 1));
1614 allof->mode = rm_allof;
1615 REGEXP_ALLOF (allof)->regexps_num = els_num;
1616 for (i = 0; i < els_num; i++)
1617 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1618 return allof;
1620 else
1621 return gen_regexp_repeat (str);
1624 /* Parse reservation STR which possibly contains separator '|'. */
1625 static regexp_t
1626 gen_regexp_oneof (const char *str)
1628 regexp_t oneof;
1629 char **oneof_vect;
1630 int els_num;
1631 int i;
1633 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1634 if (oneof_vect == NULL)
1635 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1636 if (els_num > 1)
1638 oneof = create_node (sizeof (struct regexp)
1639 + sizeof (regexp_t) * (els_num - 1));
1640 oneof->mode = rm_oneof;
1641 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1642 for (i = 0; i < els_num; i++)
1643 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1644 return oneof;
1646 else
1647 return gen_regexp_allof (str);
1650 /* Parse reservation STR which possibly contains separator ','. */
1651 static regexp_t
1652 gen_regexp_sequence (const char *str)
1654 regexp_t sequence;
1655 char **sequence_vect;
1656 int els_num;
1657 int i;
1659 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1660 if (els_num > 1)
1662 sequence = create_node (sizeof (struct regexp)
1663 + sizeof (regexp_t) * (els_num - 1));
1664 sequence->mode = rm_sequence;
1665 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1666 for (i = 0; i < els_num; i++)
1667 REGEXP_SEQUENCE (sequence)->regexps [i]
1668 = gen_regexp_oneof (sequence_vect [i]);
1669 return sequence;
1671 else
1672 return gen_regexp_oneof (str);
1675 /* Parse construction reservation STR. */
1676 static regexp_t
1677 gen_regexp (const char *str)
1679 reserv_str = str;
1680 return gen_regexp_sequence (str);;
1683 /* Process a DEFINE_RESERVATION.
1685 This gives information about a reservation of cpu units. We fill
1686 in a struct reserv_decl with information used later by
1687 `expand_automata'. */
1688 static void
1689 gen_reserv (rtx def)
1691 decl_t decl;
1693 decl = create_node (sizeof (struct decl));
1694 decl->mode = dm_reserv;
1695 decl->pos = 0;
1696 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1697 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1698 VEC_safe_push (decl_t,heap, decls, decl);
1701 /* Process a DEFINE_INSN_RESERVATION.
1703 This gives information about the reservation of cpu units by an
1704 insn. We fill a struct insn_reserv_decl with information used
1705 later by `expand_automata'. */
1706 static void
1707 gen_insn_reserv (rtx def)
1709 decl_t decl;
1711 decl = create_node (sizeof (struct decl));
1712 decl->mode = dm_insn_reserv;
1713 decl->pos = 0;
1714 DECL_INSN_RESERV (decl)->name
1715 = check_name (XSTR (def, 0), decl->pos);
1716 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1717 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1718 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1719 VEC_safe_push (decl_t,heap, decls, decl);
1724 /* The function evaluates hash value (0..UINT_MAX) of string. */
1725 static unsigned
1726 string_hash (const char *string)
1728 unsigned result, i;
1730 for (result = i = 0;*string++ != '\0'; i++)
1731 result += ((unsigned char) *string << (i % CHAR_BIT));
1732 return result;
1737 /* This page contains abstract data `table of automaton declarations'.
1738 Elements of the table is nodes representing automaton declarations.
1739 Key of the table elements is name of given automaton. Remember
1740 that automaton names have own space. */
1742 /* The function evaluates hash value of an automaton declaration. The
1743 function is used by abstract data `hashtab'. The function returns
1744 hash value (0..UINT_MAX) of given automaton declaration. */
1745 static hashval_t
1746 automaton_decl_hash (const void *automaton_decl)
1748 const decl_t decl = (decl_t) automaton_decl;
1750 gcc_assert (decl->mode != dm_automaton
1751 || DECL_AUTOMATON (decl)->name);
1752 return string_hash (DECL_AUTOMATON (decl)->name);
1755 /* The function tests automaton declarations on equality of their
1756 keys. The function is used by abstract data `hashtab'. The
1757 function returns 1 if the declarations have the same key, 0
1758 otherwise. */
1759 static int
1760 automaton_decl_eq_p (const void* automaton_decl_1,
1761 const void* automaton_decl_2)
1763 const decl_t decl1 = (decl_t) automaton_decl_1;
1764 const decl_t decl2 = (decl_t) automaton_decl_2;
1766 gcc_assert (decl1->mode == dm_automaton
1767 && DECL_AUTOMATON (decl1)->name
1768 && decl2->mode == dm_automaton
1769 && DECL_AUTOMATON (decl2)->name);
1770 return strcmp (DECL_AUTOMATON (decl1)->name,
1771 DECL_AUTOMATON (decl2)->name) == 0;
1774 /* The automaton declaration table itself is represented by the
1775 following variable. */
1776 static htab_t automaton_decl_table;
1778 /* The function inserts automaton declaration into the table. The
1779 function does nothing if an automaton declaration with the same key
1780 exists already in the table. The function returns automaton
1781 declaration node in the table with the same key as given automaton
1782 declaration node. */
1783 static decl_t
1784 insert_automaton_decl (decl_t automaton_decl)
1786 void **entry_ptr;
1788 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1789 if (*entry_ptr == NULL)
1790 *entry_ptr = (void *) automaton_decl;
1791 return (decl_t) *entry_ptr;
1794 /* The following variable value is node representing automaton
1795 declaration. The node used for searching automaton declaration
1796 with given name. */
1797 static struct decl work_automaton_decl;
1799 /* The function searches for automaton declaration in the table with
1800 the same key as node representing name of the automaton
1801 declaration. The function returns node found in the table, NULL if
1802 such node does not exist in the table. */
1803 static decl_t
1804 find_automaton_decl (const char *name)
1806 void *entry;
1808 work_automaton_decl.mode = dm_automaton;
1809 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1810 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1811 return (decl_t) entry;
1814 /* The function creates empty automaton declaration table and node
1815 representing automaton declaration and used for searching automaton
1816 declaration with given name. The function must be called only once
1817 before any work with the automaton declaration table. */
1818 static void
1819 initiate_automaton_decl_table (void)
1821 work_automaton_decl.mode = dm_automaton;
1822 automaton_decl_table = htab_create (10, automaton_decl_hash,
1823 automaton_decl_eq_p, (htab_del) 0);
1826 /* The function deletes the automaton declaration table. Only call of
1827 function `initiate_automaton_decl_table' is possible immediately
1828 after this function call. */
1829 static void
1830 finish_automaton_decl_table (void)
1832 htab_delete (automaton_decl_table);
1837 /* This page contains abstract data `table of insn declarations'.
1838 Elements of the table is nodes representing insn declarations. Key
1839 of the table elements is name of given insn (in corresponding
1840 define_insn_reservation). Remember that insn names have own
1841 space. */
1843 /* The function evaluates hash value of an insn declaration. The
1844 function is used by abstract data `hashtab'. The function returns
1845 hash value (0..UINT_MAX) of given insn declaration. */
1846 static hashval_t
1847 insn_decl_hash (const void *insn_decl)
1849 const decl_t decl = (decl_t) insn_decl;
1851 gcc_assert (decl->mode == dm_insn_reserv
1852 && DECL_INSN_RESERV (decl)->name);
1853 return string_hash (DECL_INSN_RESERV (decl)->name);
1856 /* The function tests insn declarations on equality of their keys.
1857 The function is used by abstract data `hashtab'. The function
1858 returns 1 if declarations have the same key, 0 otherwise. */
1859 static int
1860 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1862 const decl_t decl1 = (decl_t) insn_decl_1;
1863 const decl_t decl2 = (decl_t) insn_decl_2;
1865 gcc_assert (decl1->mode == dm_insn_reserv
1866 && DECL_INSN_RESERV (decl1)->name
1867 && decl2->mode == dm_insn_reserv
1868 && DECL_INSN_RESERV (decl2)->name);
1869 return strcmp (DECL_INSN_RESERV (decl1)->name,
1870 DECL_INSN_RESERV (decl2)->name) == 0;
1873 /* The insn declaration table itself is represented by the following
1874 variable. The table does not contain insn reservation
1875 declarations. */
1876 static htab_t insn_decl_table;
1878 /* The function inserts insn declaration into the table. The function
1879 does nothing if an insn declaration with the same key exists
1880 already in the table. The function returns insn declaration node
1881 in the table with the same key as given insn declaration node. */
1882 static decl_t
1883 insert_insn_decl (decl_t insn_decl)
1885 void **entry_ptr;
1887 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1888 if (*entry_ptr == NULL)
1889 *entry_ptr = (void *) insn_decl;
1890 return (decl_t) *entry_ptr;
1893 /* The following variable value is node representing insn reservation
1894 declaration. The node used for searching insn reservation
1895 declaration with given name. */
1896 static struct decl work_insn_decl;
1898 /* The function searches for insn reservation declaration in the table
1899 with the same key as node representing name of the insn reservation
1900 declaration. The function returns node found in the table, NULL if
1901 such node does not exist in the table. */
1902 static decl_t
1903 find_insn_decl (const char *name)
1905 void *entry;
1907 work_insn_decl.mode = dm_insn_reserv;
1908 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1909 entry = htab_find (insn_decl_table, &work_insn_decl);
1910 return (decl_t) entry;
1913 /* The function creates empty insn declaration table and node
1914 representing insn declaration and used for searching insn
1915 declaration with given name. The function must be called only once
1916 before any work with the insn declaration table. */
1917 static void
1918 initiate_insn_decl_table (void)
1920 work_insn_decl.mode = dm_insn_reserv;
1921 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1922 (htab_del) 0);
1925 /* The function deletes the insn declaration table. Only call of
1926 function `initiate_insn_decl_table' is possible immediately after
1927 this function call. */
1928 static void
1929 finish_insn_decl_table (void)
1931 htab_delete (insn_decl_table);
1936 /* This page contains abstract data `table of declarations'. Elements
1937 of the table is nodes representing declarations (of units and
1938 reservations). Key of the table elements is names of given
1939 declarations. */
1941 /* The function evaluates hash value of a declaration. The function
1942 is used by abstract data `hashtab'. The function returns hash
1943 value (0..UINT_MAX) of given declaration. */
1944 static hashval_t
1945 decl_hash (const void *decl)
1947 const decl_t d = (const decl_t) decl;
1949 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1950 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1951 return string_hash (d->mode == dm_unit
1952 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1955 /* The function tests declarations on equality of their keys. The
1956 function is used by abstract data 'hashtab'. The function
1957 returns 1 if the declarations have the same key, 0 otherwise. */
1958 static int
1959 decl_eq_p (const void *decl_1, const void *decl_2)
1961 const decl_t d1 = (const decl_t) decl_1;
1962 const decl_t d2 = (const decl_t) decl_2;
1964 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1965 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1966 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1967 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1968 return strcmp ((d1->mode == dm_unit
1969 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1970 (d2->mode == dm_unit
1971 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1974 /* The declaration table itself is represented by the following
1975 variable. */
1976 static htab_t decl_table;
1978 /* The function inserts declaration into the table. The function does
1979 nothing if a declaration with the same key exists already in the
1980 table. The function returns declaration node in the table with the
1981 same key as given declaration node. */
1983 static decl_t
1984 insert_decl (decl_t decl)
1986 void **entry_ptr;
1988 entry_ptr = htab_find_slot (decl_table, decl, 1);
1989 if (*entry_ptr == NULL)
1990 *entry_ptr = (void *) decl;
1991 return (decl_t) *entry_ptr;
1994 /* The following variable value is node representing declaration. The
1995 node used for searching declaration with given name. */
1996 static struct decl work_decl;
1998 /* The function searches for declaration in the table with the same
1999 key as node representing name of the declaration. The function
2000 returns node found in the table, NULL if such node does not exist
2001 in the table. */
2002 static decl_t
2003 find_decl (const char *name)
2005 void *entry;
2007 work_decl.mode = dm_unit;
2008 DECL_UNIT (&work_decl)->name = name;
2009 entry = htab_find (decl_table, &work_decl);
2010 return (decl_t) entry;
2013 /* The function creates empty declaration table and node representing
2014 declaration and used for searching declaration with given name.
2015 The function must be called only once before any work with the
2016 declaration table. */
2017 static void
2018 initiate_decl_table (void)
2020 work_decl.mode = dm_unit;
2021 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2024 /* The function deletes the declaration table. Only call of function
2025 `initiate_declaration_table' is possible immediately after this
2026 function call. */
2027 static void
2028 finish_decl_table (void)
2030 htab_delete (decl_table);
2035 /* This page contains checker of pipeline hazard description. */
2037 /* Checking NAMES in an exclusion clause vector and returning formed
2038 unit_set_el_list. */
2039 static unit_set_el_t
2040 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2042 unit_set_el_t el_list;
2043 unit_set_el_t last_el;
2044 unit_set_el_t new_el;
2045 decl_t decl_in_table;
2046 int i;
2048 el_list = NULL;
2049 last_el = NULL;
2050 for (i = 0; i < num; i++)
2052 decl_in_table = find_decl (names [i]);
2053 if (decl_in_table == NULL)
2054 error ("unit `%s' in exclusion is not declared", names [i]);
2055 else if (decl_in_table->mode != dm_unit)
2056 error ("`%s' in exclusion is not unit", names [i]);
2057 else
2059 new_el = create_node (sizeof (struct unit_set_el));
2060 new_el->unit_decl = DECL_UNIT (decl_in_table);
2061 new_el->next_unit_set_el = NULL;
2062 if (last_el == NULL)
2063 el_list = last_el = new_el;
2064 else
2066 last_el->next_unit_set_el = new_el;
2067 last_el = last_el->next_unit_set_el;
2071 return el_list;
2074 /* The function adds each element from SOURCE_LIST to the exclusion
2075 list of the each element from DEST_LIST. Checking situation "unit
2076 excludes itself". */
2077 static void
2078 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2079 pos_t excl_pos ATTRIBUTE_UNUSED)
2081 unit_set_el_t dst;
2082 unit_set_el_t src;
2083 unit_set_el_t curr_el;
2084 unit_set_el_t prev_el;
2085 unit_set_el_t copy;
2087 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2088 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2090 if (dst->unit_decl == src->unit_decl)
2092 error ("unit `%s' excludes itself", src->unit_decl->name);
2093 continue;
2095 if (dst->unit_decl->automaton_name != NULL
2096 && src->unit_decl->automaton_name != NULL
2097 && strcmp (dst->unit_decl->automaton_name,
2098 src->unit_decl->automaton_name) != 0)
2100 error ("units `%s' and `%s' in exclusion set belong to different automata",
2101 src->unit_decl->name, dst->unit_decl->name);
2102 continue;
2104 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2105 curr_el != NULL;
2106 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2107 if (curr_el->unit_decl == src->unit_decl)
2108 break;
2109 if (curr_el == NULL)
2111 /* Element not found - insert. */
2112 copy = copy_node (src, sizeof (*src));
2113 copy->next_unit_set_el = NULL;
2114 if (prev_el == NULL)
2115 dst->unit_decl->excl_list = copy;
2116 else
2117 prev_el->next_unit_set_el = copy;
2122 /* Checking NAMES in presence/absence clause and returning the
2123 formed unit_set_el_list. The function is called only after
2124 processing all exclusion sets. */
2125 static unit_set_el_t
2126 process_presence_absence_names (char **names, int num,
2127 pos_t req_pos ATTRIBUTE_UNUSED,
2128 int presence_p, int final_p)
2130 unit_set_el_t el_list;
2131 unit_set_el_t last_el;
2132 unit_set_el_t new_el;
2133 decl_t decl_in_table;
2134 int i;
2136 el_list = NULL;
2137 last_el = NULL;
2138 for (i = 0; i < num; i++)
2140 decl_in_table = find_decl (names [i]);
2141 if (decl_in_table == NULL)
2142 error ((presence_p
2143 ? (final_p
2144 ? "unit `%s' in final presence set is not declared"
2145 : "unit `%s' in presence set is not declared")
2146 : (final_p
2147 ? "unit `%s' in final absence set is not declared"
2148 : "unit `%s' in absence set is not declared")), names [i]);
2149 else if (decl_in_table->mode != dm_unit)
2150 error ((presence_p
2151 ? (final_p
2152 ? "`%s' in final presence set is not unit"
2153 : "`%s' in presence set is not unit")
2154 : (final_p
2155 ? "`%s' in final absence set is not unit"
2156 : "`%s' in absence set is not unit")), names [i]);
2157 else
2159 new_el = create_node (sizeof (struct unit_set_el));
2160 new_el->unit_decl = DECL_UNIT (decl_in_table);
2161 new_el->next_unit_set_el = NULL;
2162 if (last_el == NULL)
2163 el_list = last_el = new_el;
2164 else
2166 last_el->next_unit_set_el = new_el;
2167 last_el = last_el->next_unit_set_el;
2171 return el_list;
2174 /* Checking NAMES in patterns of a presence/absence clause and
2175 returning the formed pattern_set_el_list. The function is called
2176 only after processing all exclusion sets. */
2177 static pattern_set_el_t
2178 process_presence_absence_patterns (char ***patterns, int num,
2179 pos_t req_pos ATTRIBUTE_UNUSED,
2180 int presence_p, int final_p)
2182 pattern_set_el_t el_list;
2183 pattern_set_el_t last_el;
2184 pattern_set_el_t new_el;
2185 decl_t decl_in_table;
2186 int i, j;
2188 el_list = NULL;
2189 last_el = NULL;
2190 for (i = 0; i < num; i++)
2192 for (j = 0; patterns [i] [j] != NULL; j++)
2194 new_el = create_node (sizeof (struct pattern_set_el)
2195 + sizeof (struct unit_decl *) * j);
2196 new_el->unit_decls
2197 = (struct unit_decl **) ((char *) new_el
2198 + sizeof (struct pattern_set_el));
2199 new_el->next_pattern_set_el = NULL;
2200 if (last_el == NULL)
2201 el_list = last_el = new_el;
2202 else
2204 last_el->next_pattern_set_el = new_el;
2205 last_el = last_el->next_pattern_set_el;
2207 new_el->units_num = 0;
2208 for (j = 0; patterns [i] [j] != NULL; j++)
2210 decl_in_table = find_decl (patterns [i] [j]);
2211 if (decl_in_table == NULL)
2212 error ((presence_p
2213 ? (final_p
2214 ? "unit `%s' in final presence set is not declared"
2215 : "unit `%s' in presence set is not declared")
2216 : (final_p
2217 ? "unit `%s' in final absence set is not declared"
2218 : "unit `%s' in absence set is not declared")),
2219 patterns [i] [j]);
2220 else if (decl_in_table->mode != dm_unit)
2221 error ((presence_p
2222 ? (final_p
2223 ? "`%s' in final presence set is not unit"
2224 : "`%s' in presence set is not unit")
2225 : (final_p
2226 ? "`%s' in final absence set is not unit"
2227 : "`%s' in absence set is not unit")),
2228 patterns [i] [j]);
2229 else
2231 new_el->unit_decls [new_el->units_num]
2232 = DECL_UNIT (decl_in_table);
2233 new_el->units_num++;
2237 return el_list;
2240 /* The function adds each element from PATTERN_LIST to presence (if
2241 PRESENCE_P) or absence list of the each element from DEST_LIST.
2242 Checking situations "unit requires own absence", and "unit excludes
2243 and requires presence of ...", "unit requires absence and presence
2244 of ...", "units in (final) presence set belong to different
2245 automata", and "units in (final) absence set belong to different
2246 automata". Remember that we process absence sets only after all
2247 presence sets. */
2248 static void
2249 add_presence_absence (unit_set_el_t dest_list,
2250 pattern_set_el_t pattern_list,
2251 pos_t req_pos ATTRIBUTE_UNUSED,
2252 int presence_p, int final_p)
2254 unit_set_el_t dst;
2255 pattern_set_el_t pat;
2256 struct unit_decl *unit;
2257 unit_set_el_t curr_excl_el;
2258 pattern_set_el_t curr_pat_el;
2259 pattern_set_el_t prev_el;
2260 pattern_set_el_t copy;
2261 int i;
2262 int no_error_flag;
2264 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2265 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2267 for (i = 0; i < pat->units_num; i++)
2269 unit = pat->unit_decls [i];
2270 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2272 error ("unit `%s' requires own absence", unit->name);
2273 continue;
2275 if (dst->unit_decl->automaton_name != NULL
2276 && unit->automaton_name != NULL
2277 && strcmp (dst->unit_decl->automaton_name,
2278 unit->automaton_name) != 0)
2280 error ((presence_p
2281 ? (final_p
2282 ? "units `%s' and `%s' in final presence set belong to different automata"
2283 : "units `%s' and `%s' in presence set belong to different automata")
2284 : (final_p
2285 ? "units `%s' and `%s' in final absence set belong to different automata"
2286 : "units `%s' and `%s' in absence set belong to different automata")),
2287 unit->name, dst->unit_decl->name);
2288 continue;
2290 no_error_flag = 1;
2291 if (presence_p)
2292 for (curr_excl_el = dst->unit_decl->excl_list;
2293 curr_excl_el != NULL;
2294 curr_excl_el = curr_excl_el->next_unit_set_el)
2296 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2298 if (!w_flag)
2300 error ("unit `%s' excludes and requires presence of `%s'",
2301 dst->unit_decl->name, unit->name);
2302 no_error_flag = 0;
2304 else
2305 warning
2306 (0, "unit `%s' excludes and requires presence of `%s'",
2307 dst->unit_decl->name, unit->name);
2310 else if (pat->units_num == 1)
2311 for (curr_pat_el = dst->unit_decl->presence_list;
2312 curr_pat_el != NULL;
2313 curr_pat_el = curr_pat_el->next_pattern_set_el)
2314 if (curr_pat_el->units_num == 1
2315 && unit == curr_pat_el->unit_decls [0])
2317 if (!w_flag)
2319 error
2320 ("unit `%s' requires absence and presence of `%s'",
2321 dst->unit_decl->name, unit->name);
2322 no_error_flag = 0;
2324 else
2325 warning
2326 (0, "unit `%s' requires absence and presence of `%s'",
2327 dst->unit_decl->name, unit->name);
2329 if (no_error_flag)
2331 for (prev_el = (presence_p
2332 ? (final_p
2333 ? dst->unit_decl->final_presence_list
2334 : dst->unit_decl->final_presence_list)
2335 : (final_p
2336 ? dst->unit_decl->final_absence_list
2337 : dst->unit_decl->absence_list));
2338 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2339 prev_el = prev_el->next_pattern_set_el)
2341 copy = copy_node (pat, sizeof (*pat));
2342 copy->next_pattern_set_el = NULL;
2343 if (prev_el == NULL)
2345 if (presence_p)
2347 if (final_p)
2348 dst->unit_decl->final_presence_list = copy;
2349 else
2350 dst->unit_decl->presence_list = copy;
2352 else if (final_p)
2353 dst->unit_decl->final_absence_list = copy;
2354 else
2355 dst->unit_decl->absence_list = copy;
2357 else
2358 prev_el->next_pattern_set_el = copy;
2365 /* The function searches for bypass with given IN_INSN_RESERV in given
2366 BYPASS_LIST. */
2367 static struct bypass_decl *
2368 find_bypass (struct bypass_decl *bypass_list,
2369 struct insn_reserv_decl *in_insn_reserv)
2371 struct bypass_decl *bypass;
2373 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2374 if (bypass->in_insn_reserv == in_insn_reserv)
2375 break;
2376 return bypass;
2379 /* The function processes pipeline description declarations, checks
2380 their correctness, and forms exclusion/presence/absence sets. */
2381 static void
2382 process_decls (void)
2384 decl_t decl;
2385 decl_t automaton_decl;
2386 decl_t decl_in_table;
2387 decl_t out_insn_reserv;
2388 decl_t in_insn_reserv;
2389 struct bypass_decl *bypass;
2390 int automaton_presence;
2391 int i;
2393 /* Checking repeated automata declarations. */
2394 automaton_presence = 0;
2395 for (i = 0; i < description->decls_num; i++)
2397 decl = description->decls [i];
2398 if (decl->mode == dm_automaton)
2400 automaton_presence = 1;
2401 decl_in_table = insert_automaton_decl (decl);
2402 if (decl_in_table != decl)
2404 if (!w_flag)
2405 error ("repeated declaration of automaton `%s'",
2406 DECL_AUTOMATON (decl)->name);
2407 else
2408 warning (0, "repeated declaration of automaton `%s'",
2409 DECL_AUTOMATON (decl)->name);
2413 /* Checking undeclared automata, repeated declarations (except for
2414 automata) and correctness of their attributes (insn latency times
2415 etc.). */
2416 for (i = 0; i < description->decls_num; i++)
2418 decl = description->decls [i];
2419 if (decl->mode == dm_insn_reserv)
2421 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2422 error ("define_insn_reservation `%s' has negative latency time",
2423 DECL_INSN_RESERV (decl)->name);
2424 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2425 description->insns_num++;
2426 decl_in_table = insert_insn_decl (decl);
2427 if (decl_in_table != decl)
2428 error ("`%s' is already used as insn reservation name",
2429 DECL_INSN_RESERV (decl)->name);
2431 else if (decl->mode == dm_bypass)
2433 if (DECL_BYPASS (decl)->latency < 0)
2434 error ("define_bypass `%s - %s' has negative latency time",
2435 DECL_BYPASS (decl)->out_insn_name,
2436 DECL_BYPASS (decl)->in_insn_name);
2438 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2440 if (decl->mode == dm_unit)
2442 DECL_UNIT (decl)->automaton_decl = NULL;
2443 if (DECL_UNIT (decl)->automaton_name != NULL)
2445 automaton_decl
2446 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2447 if (automaton_decl == NULL)
2448 error ("automaton `%s' is not declared",
2449 DECL_UNIT (decl)->automaton_name);
2450 else
2452 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2453 DECL_UNIT (decl)->automaton_decl
2454 = DECL_AUTOMATON (automaton_decl);
2457 else if (automaton_presence)
2458 error ("define_unit `%s' without automaton when one defined",
2459 DECL_UNIT (decl)->name);
2460 DECL_UNIT (decl)->unit_num = description->units_num;
2461 description->units_num++;
2462 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2464 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2465 continue;
2467 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2469 else
2471 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2473 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2474 continue;
2476 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2478 if (decl_in_table == NULL)
2479 decl_in_table = insert_decl (decl);
2480 else
2482 if (decl->mode == dm_unit)
2483 error ("repeated declaration of unit `%s'",
2484 DECL_UNIT (decl)->name);
2485 else
2486 error ("repeated declaration of reservation `%s'",
2487 DECL_RESERV (decl)->name);
2491 /* Check bypasses and form list of bypasses for each (output)
2492 insn. */
2493 for (i = 0; i < description->decls_num; i++)
2495 decl = description->decls [i];
2496 if (decl->mode == dm_bypass)
2498 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2499 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2500 if (out_insn_reserv == NULL)
2501 error ("there is no insn reservation `%s'",
2502 DECL_BYPASS (decl)->out_insn_name);
2503 else if (in_insn_reserv == NULL)
2504 error ("there is no insn reservation `%s'",
2505 DECL_BYPASS (decl)->in_insn_name);
2506 else
2508 DECL_BYPASS (decl)->out_insn_reserv
2509 = DECL_INSN_RESERV (out_insn_reserv);
2510 DECL_BYPASS (decl)->in_insn_reserv
2511 = DECL_INSN_RESERV (in_insn_reserv);
2512 bypass
2513 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2514 DECL_BYPASS (decl)->in_insn_reserv);
2515 if (bypass != NULL)
2517 if (DECL_BYPASS (decl)->latency == bypass->latency)
2519 if (!w_flag)
2520 error
2521 ("the same bypass `%s - %s' is already defined",
2522 DECL_BYPASS (decl)->out_insn_name,
2523 DECL_BYPASS (decl)->in_insn_name);
2524 else
2525 warning
2526 (0, "the same bypass `%s - %s' is already defined",
2527 DECL_BYPASS (decl)->out_insn_name,
2528 DECL_BYPASS (decl)->in_insn_name);
2530 else
2531 error ("bypass `%s - %s' is already defined",
2532 DECL_BYPASS (decl)->out_insn_name,
2533 DECL_BYPASS (decl)->in_insn_name);
2535 else
2537 DECL_BYPASS (decl)->next
2538 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2539 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2540 = DECL_BYPASS (decl);
2546 /* Check exclusion set declarations and form exclusion sets. */
2547 for (i = 0; i < description->decls_num; i++)
2549 decl = description->decls [i];
2550 if (decl->mode == dm_excl)
2552 unit_set_el_t unit_set_el_list;
2553 unit_set_el_t unit_set_el_list_2;
2555 unit_set_el_list
2556 = process_excls (DECL_EXCL (decl)->names,
2557 DECL_EXCL (decl)->first_list_length, decl->pos);
2558 unit_set_el_list_2
2559 = process_excls (&DECL_EXCL (decl)->names
2560 [DECL_EXCL (decl)->first_list_length],
2561 DECL_EXCL (decl)->all_names_num
2562 - DECL_EXCL (decl)->first_list_length,
2563 decl->pos);
2564 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2565 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2569 /* Check presence set declarations and form presence sets. */
2570 for (i = 0; i < description->decls_num; i++)
2572 decl = description->decls [i];
2573 if (decl->mode == dm_presence)
2575 unit_set_el_t unit_set_el_list;
2576 pattern_set_el_t pattern_set_el_list;
2578 unit_set_el_list
2579 = process_presence_absence_names
2580 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2581 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2582 pattern_set_el_list
2583 = process_presence_absence_patterns
2584 (DECL_PRESENCE (decl)->patterns,
2585 DECL_PRESENCE (decl)->patterns_num,
2586 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2587 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2588 decl->pos, TRUE,
2589 DECL_PRESENCE (decl)->final_p);
2593 /* Check absence set declarations and form absence sets. */
2594 for (i = 0; i < description->decls_num; i++)
2596 decl = description->decls [i];
2597 if (decl->mode == dm_absence)
2599 unit_set_el_t unit_set_el_list;
2600 pattern_set_el_t pattern_set_el_list;
2602 unit_set_el_list
2603 = process_presence_absence_names
2604 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2605 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2606 pattern_set_el_list
2607 = process_presence_absence_patterns
2608 (DECL_ABSENCE (decl)->patterns,
2609 DECL_ABSENCE (decl)->patterns_num,
2610 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2611 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2612 decl->pos, FALSE,
2613 DECL_ABSENCE (decl)->final_p);
2618 /* The following function checks that declared automaton is used. If
2619 the automaton is not used, the function fixes error/warning. The
2620 following function must be called only after `process_decls'. */
2621 static void
2622 check_automaton_usage (void)
2624 decl_t decl;
2625 int i;
2627 for (i = 0; i < description->decls_num; i++)
2629 decl = description->decls [i];
2630 if (decl->mode == dm_automaton
2631 && !DECL_AUTOMATON (decl)->automaton_is_used)
2633 if (!w_flag)
2634 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2635 else
2636 warning (0, "automaton `%s' is not used",
2637 DECL_AUTOMATON (decl)->name);
2642 /* The following recursive function processes all regexp in order to
2643 fix usage of units or reservations and to fix errors of undeclared
2644 name. The function may change unit_regexp onto reserv_regexp.
2645 Remember that reserv_regexp does not exist before the function
2646 call. */
2647 static regexp_t
2648 process_regexp (regexp_t regexp)
2650 decl_t decl_in_table;
2651 regexp_t new_regexp;
2652 int i;
2654 switch (regexp->mode)
2656 case rm_unit:
2657 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2658 if (decl_in_table == NULL)
2659 error ("undeclared unit or reservation `%s'",
2660 REGEXP_UNIT (regexp)->name);
2661 else
2662 switch (decl_in_table->mode)
2664 case dm_unit:
2665 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2666 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2667 break;
2669 case dm_reserv:
2670 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2671 new_regexp = create_node (sizeof (struct regexp));
2672 new_regexp->mode = rm_reserv;
2673 new_regexp->pos = regexp->pos;
2674 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2675 REGEXP_RESERV (new_regexp)->reserv_decl
2676 = DECL_RESERV (decl_in_table);
2677 regexp = new_regexp;
2678 break;
2680 default:
2681 gcc_unreachable ();
2683 break;
2684 case rm_sequence:
2685 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2686 REGEXP_SEQUENCE (regexp)->regexps [i]
2687 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2688 break;
2689 case rm_allof:
2690 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2691 REGEXP_ALLOF (regexp)->regexps [i]
2692 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2693 break;
2694 case rm_oneof:
2695 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2696 REGEXP_ONEOF (regexp)->regexps [i]
2697 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2698 break;
2699 case rm_repeat:
2700 REGEXP_REPEAT (regexp)->regexp
2701 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2702 break;
2703 case rm_nothing:
2704 break;
2705 default:
2706 gcc_unreachable ();
2708 return regexp;
2711 /* The following function processes regexp of define_reservation and
2712 define_insn_reservation with the aid of function
2713 `process_regexp'. */
2714 static void
2715 process_regexp_decls (void)
2717 decl_t decl;
2718 int i;
2720 for (i = 0; i < description->decls_num; i++)
2722 decl = description->decls [i];
2723 if (decl->mode == dm_reserv)
2724 DECL_RESERV (decl)->regexp
2725 = process_regexp (DECL_RESERV (decl)->regexp);
2726 else if (decl->mode == dm_insn_reserv)
2727 DECL_INSN_RESERV (decl)->regexp
2728 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2732 /* The following function checks that declared unit is used. If the
2733 unit is not used, the function fixes errors/warnings. The
2734 following function must be called only after `process_decls',
2735 `process_regexp_decls'. */
2736 static void
2737 check_usage (void)
2739 decl_t decl;
2740 int i;
2742 for (i = 0; i < description->decls_num; i++)
2744 decl = description->decls [i];
2745 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2747 if (!w_flag)
2748 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2749 else
2750 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2752 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2754 if (!w_flag)
2755 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2756 else
2757 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2762 /* The following variable value is number of reservation being
2763 processed on loop recognition. */
2764 static int curr_loop_pass_num;
2766 /* The following recursive function returns nonzero value if REGEXP
2767 contains given decl or reservations in given regexp refers for
2768 given decl. */
2769 static int
2770 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2772 int i;
2774 if (regexp == NULL)
2775 return 0;
2776 switch (regexp->mode)
2778 case rm_unit:
2779 return 0;
2781 case rm_reserv:
2782 if (start_decl->mode == dm_reserv
2783 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2784 return 1;
2785 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2786 == curr_loop_pass_num)
2787 /* declaration has been processed. */
2788 return 0;
2789 else
2791 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2792 = curr_loop_pass_num;
2793 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2794 start_decl);
2797 case rm_sequence:
2798 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2799 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2800 return 1;
2801 return 0;
2803 case rm_allof:
2804 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2805 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2806 return 1;
2807 return 0;
2809 case rm_oneof:
2810 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2811 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2812 return 1;
2813 return 0;
2815 case rm_repeat:
2816 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2818 case rm_nothing:
2819 return 0;
2821 default:
2822 gcc_unreachable ();
2826 /* The following function fixes errors "cycle in definition ...". The
2827 function uses function `loop_in_regexp' for that. */
2828 static void
2829 check_loops_in_regexps (void)
2831 decl_t decl;
2832 int i;
2834 for (i = 0; i < description->decls_num; i++)
2836 decl = description->decls [i];
2837 if (decl->mode == dm_reserv)
2838 DECL_RESERV (decl)->loop_pass_num = 0;
2840 for (i = 0; i < description->decls_num; i++)
2842 decl = description->decls [i];
2843 curr_loop_pass_num = i;
2845 if (decl->mode == dm_reserv)
2847 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2848 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2850 gcc_assert (DECL_RESERV (decl)->regexp);
2851 error ("cycle in definition of reservation `%s'",
2852 DECL_RESERV (decl)->name);
2858 /* The function recursively processes IR of reservation and defines
2859 max and min cycle for reservation of unit. */
2860 static void
2861 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2862 int min_start_cycle, int *max_finish_cycle,
2863 int *min_finish_cycle)
2865 int i;
2867 switch (regexp->mode)
2869 case rm_unit:
2870 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2871 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2872 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2873 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2874 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2875 *max_finish_cycle = max_start_cycle;
2876 *min_finish_cycle = min_start_cycle;
2877 break;
2879 case rm_reserv:
2880 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2881 max_start_cycle, min_start_cycle,
2882 max_finish_cycle, min_finish_cycle);
2883 break;
2885 case rm_repeat:
2886 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2888 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2889 max_start_cycle, min_start_cycle,
2890 max_finish_cycle, min_finish_cycle);
2891 max_start_cycle = *max_finish_cycle + 1;
2892 min_start_cycle = *min_finish_cycle + 1;
2894 break;
2896 case rm_sequence:
2897 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2899 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2900 max_start_cycle, min_start_cycle,
2901 max_finish_cycle, min_finish_cycle);
2902 max_start_cycle = *max_finish_cycle + 1;
2903 min_start_cycle = *min_finish_cycle + 1;
2905 break;
2907 case rm_allof:
2909 int max_cycle = 0;
2910 int min_cycle = 0;
2912 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2914 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2915 max_start_cycle, min_start_cycle,
2916 max_finish_cycle, min_finish_cycle);
2917 if (max_cycle < *max_finish_cycle)
2918 max_cycle = *max_finish_cycle;
2919 if (i == 0 || min_cycle > *min_finish_cycle)
2920 min_cycle = *min_finish_cycle;
2922 *max_finish_cycle = max_cycle;
2923 *min_finish_cycle = min_cycle;
2925 break;
2927 case rm_oneof:
2929 int max_cycle = 0;
2930 int min_cycle = 0;
2932 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2934 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2935 max_start_cycle, min_start_cycle,
2936 max_finish_cycle, min_finish_cycle);
2937 if (max_cycle < *max_finish_cycle)
2938 max_cycle = *max_finish_cycle;
2939 if (i == 0 || min_cycle > *min_finish_cycle)
2940 min_cycle = *min_finish_cycle;
2942 *max_finish_cycle = max_cycle;
2943 *min_finish_cycle = min_cycle;
2945 break;
2947 case rm_nothing:
2948 *max_finish_cycle = max_start_cycle;
2949 *min_finish_cycle = min_start_cycle;
2950 break;
2952 default:
2953 gcc_unreachable ();
2957 /* The following function is called only for correct program. The
2958 function defines max reservation of insns in cycles. */
2959 static void
2960 evaluate_max_reserv_cycles (void)
2962 int max_insn_cycles_num;
2963 int min_insn_cycles_num;
2964 decl_t decl;
2965 int i;
2967 description->max_insn_reserv_cycles = 0;
2968 for (i = 0; i < description->decls_num; i++)
2970 decl = description->decls [i];
2971 if (decl->mode == dm_insn_reserv)
2973 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2974 &max_insn_cycles_num, &min_insn_cycles_num);
2975 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2976 description->max_insn_reserv_cycles = max_insn_cycles_num;
2979 description->max_insn_reserv_cycles++;
2982 /* The following function calls functions for checking all
2983 description. */
2984 static void
2985 check_all_description (void)
2987 process_decls ();
2988 check_automaton_usage ();
2989 process_regexp_decls ();
2990 check_usage ();
2991 check_loops_in_regexps ();
2992 if (!have_error)
2993 evaluate_max_reserv_cycles ();
2998 /* The page contains abstract data `ticker'. This data is used to
2999 report time of different phases of building automata. It is
3000 possibly to write a description for which automata will be built
3001 during several minutes even on fast machine. */
3003 /* The following function creates ticker and makes it active. */
3004 static ticker_t
3005 create_ticker (void)
3007 ticker_t ticker;
3009 ticker.modified_creation_time = get_run_time ();
3010 ticker.incremented_off_time = 0;
3011 return ticker;
3014 /* The following function switches off given ticker. */
3015 static void
3016 ticker_off (ticker_t *ticker)
3018 if (ticker->incremented_off_time == 0)
3019 ticker->incremented_off_time = get_run_time () + 1;
3022 /* The following function switches on given ticker. */
3023 static void
3024 ticker_on (ticker_t *ticker)
3026 if (ticker->incremented_off_time != 0)
3028 ticker->modified_creation_time
3029 += get_run_time () - ticker->incremented_off_time + 1;
3030 ticker->incremented_off_time = 0;
3034 /* The following function returns current time in milliseconds since
3035 the moment when given ticker was created. */
3036 static int
3037 active_time (ticker_t ticker)
3039 if (ticker.incremented_off_time != 0)
3040 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3041 else
3042 return get_run_time () - ticker.modified_creation_time;
3045 /* The following function returns string representation of active time
3046 of given ticker. The result is string representation of seconds
3047 with accuracy of 1/100 second. Only result of the last call of the
3048 function exists. Therefore the following code is not correct
3050 printf ("parser time: %s\ngeneration time: %s\n",
3051 active_time_string (parser_ticker),
3052 active_time_string (generation_ticker));
3054 Correct code has to be the following
3056 printf ("parser time: %s\n", active_time_string (parser_ticker));
3057 printf ("generation time: %s\n",
3058 active_time_string (generation_ticker));
3061 static void
3062 print_active_time (FILE *f, ticker_t ticker)
3064 int msecs;
3066 msecs = active_time (ticker);
3067 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3072 /* The following variable value is number of automaton which are
3073 really being created. This value is defined on the base of
3074 argument of option `-split'. If the variable has zero value the
3075 number of automata is defined by the constructions `%automaton'.
3076 This case occurs when option `-split' is absent or has zero
3077 argument. If constructions `define_automaton' is absent only one
3078 automaton is created. */
3079 static int automata_num;
3081 /* The following variable values are times of
3082 o transformation of regular expressions
3083 o building NDFA (DFA if !ndfa_flag)
3084 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3085 o DFA minimization
3086 o building insn equivalence classes
3087 o all previous ones
3088 o code output */
3089 static ticker_t transform_time;
3090 static ticker_t NDFA_time;
3091 static ticker_t NDFA_to_DFA_time;
3092 static ticker_t minimize_time;
3093 static ticker_t equiv_time;
3094 static ticker_t automaton_generation_time;
3095 static ticker_t output_time;
3097 /* The following variable values are times of
3098 all checking
3099 all generation
3100 all pipeline hazard translator work */
3101 static ticker_t check_time;
3102 static ticker_t generation_time;
3103 static ticker_t all_time;
3107 /* Pseudo insn decl which denotes advancing cycle. */
3108 static decl_t advance_cycle_insn_decl;
3109 static void
3110 add_advance_cycle_insn_decl (void)
3112 advance_cycle_insn_decl = create_node (sizeof (struct decl));
3113 advance_cycle_insn_decl->mode = dm_insn_reserv;
3114 advance_cycle_insn_decl->pos = no_pos;
3115 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3116 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3117 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3118 = description->insns_num;
3119 description->decls [description->decls_num] = advance_cycle_insn_decl;
3120 description->decls_num++;
3121 description->insns_num++;
3125 /* Abstract data `alternative states' which represents
3126 nondeterministic nature of the description (see comments for
3127 structures alt_state and state). */
3129 /* List of free states. */
3130 static alt_state_t first_free_alt_state;
3132 #ifndef NDEBUG
3133 /* The following variables is maximal number of allocated nodes
3134 alt_state. */
3135 static int allocated_alt_states_num = 0;
3136 #endif
3138 /* The following function returns free node alt_state. It may be new
3139 allocated node or node freed earlier. */
3140 static alt_state_t
3141 get_free_alt_state (void)
3143 alt_state_t result;
3145 if (first_free_alt_state != NULL)
3147 result = first_free_alt_state;
3148 first_free_alt_state = first_free_alt_state->next_alt_state;
3150 else
3152 #ifndef NDEBUG
3153 allocated_alt_states_num++;
3154 #endif
3155 result = create_node (sizeof (struct alt_state));
3157 result->state = NULL;
3158 result->next_alt_state = NULL;
3159 result->next_sorted_alt_state = NULL;
3160 return result;
3163 /* The function frees node ALT_STATE. */
3164 static void
3165 free_alt_state (alt_state_t alt_state)
3167 if (alt_state == NULL)
3168 return;
3169 alt_state->next_alt_state = first_free_alt_state;
3170 first_free_alt_state = alt_state;
3173 /* The function frees list started with node ALT_STATE_LIST. */
3174 static void
3175 free_alt_states (alt_state_t alt_states_list)
3177 alt_state_t curr_alt_state;
3178 alt_state_t next_alt_state;
3180 for (curr_alt_state = alt_states_list;
3181 curr_alt_state != NULL;
3182 curr_alt_state = next_alt_state)
3184 next_alt_state = curr_alt_state->next_alt_state;
3185 free_alt_state (curr_alt_state);
3189 /* The function compares unique numbers of alt states. */
3190 static int
3191 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3193 if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3194 == (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3195 return 0;
3196 else if ((*(alt_state_t *) alt_state_ptr_1)->state->unique_num
3197 < (*(alt_state_t *) alt_state_ptr_2)->state->unique_num)
3198 return -1;
3199 else
3200 return 1;
3203 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3204 states from the list. The comparison key is alt state unique
3205 number. */
3207 static alt_state_t
3208 uniq_sort_alt_states (alt_state_t alt_states_list)
3210 alt_state_t curr_alt_state;
3211 VEC(alt_state_t,heap) *alt_states;
3212 size_t i;
3213 size_t prev_unique_state_ind;
3214 alt_state_t result;
3216 if (alt_states_list == 0)
3217 return 0;
3218 if (alt_states_list->next_alt_state == 0)
3219 return alt_states_list;
3221 alt_states = VEC_alloc (alt_state_t,heap, 150);
3222 for (curr_alt_state = alt_states_list;
3223 curr_alt_state != NULL;
3224 curr_alt_state = curr_alt_state->next_alt_state)
3225 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3227 qsort (VEC_address (alt_state_t, alt_states),
3228 VEC_length (alt_state_t, alt_states),
3229 sizeof (alt_state_t), alt_state_cmp);
3231 prev_unique_state_ind = 0;
3232 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3233 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3234 != VEC_index (alt_state_t, alt_states, i)->state)
3236 prev_unique_state_ind++;
3237 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3238 VEC_index (alt_state_t, alt_states, i));
3240 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3242 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3243 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3244 = VEC_index (alt_state_t, alt_states, i);
3245 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3247 result = VEC_index (alt_state_t, alt_states, 0);
3249 VEC_free (alt_state_t,heap, alt_states);
3250 return result;
3253 /* The function checks equality of alt state lists. Remember that the
3254 lists must be already sorted by the previous function. */
3255 static int
3256 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3258 while (alt_states_1 != NULL && alt_states_2 != NULL
3259 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3261 alt_states_1 = alt_states_1->next_sorted_alt_state;
3262 alt_states_2 = alt_states_2->next_sorted_alt_state;
3264 return alt_states_1 == alt_states_2;
3267 /* Initialization of the abstract data. */
3268 static void
3269 initiate_alt_states (void)
3271 first_free_alt_state = NULL;
3274 /* Finishing work with the abstract data. */
3275 static void
3276 finish_alt_states (void)
3282 /* The page contains macros for work with bits strings. We could use
3283 standard gcc bitmap or sbitmap but it would result in difficulties
3284 of building canadian cross. */
3286 /* Set bit number bitno in the bit string. The macro is not side
3287 effect proof. */
3288 #define SET_BIT(bitstring, bitno) \
3289 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3291 #define CLEAR_BIT(bitstring, bitno) \
3292 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3294 /* Test if bit number bitno in the bitstring is set. The macro is not
3295 side effect proof. */
3296 #define TEST_BIT(bitstring, bitno) \
3297 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3301 /* This page contains abstract data `state'. */
3303 /* Maximal length of reservations in cycles (>= 1). */
3304 static int max_cycles_num;
3306 /* Number of set elements (see type set_el_t) needed for
3307 representation of one cycle reservation. It is depended on units
3308 number. */
3309 static int els_in_cycle_reserv;
3311 /* Number of set elements (see type set_el_t) needed for
3312 representation of maximal length reservation. Deterministic
3313 reservation is stored as set (bit string) of length equal to the
3314 variable value * number of bits in set_el_t. */
3315 static int els_in_reservs;
3317 /* Array of pointers to unit declarations. */
3318 static unit_decl_t *units_array;
3320 /* Temporary reservation of maximal length. */
3321 static reserv_sets_t temp_reserv;
3323 /* The state table itself is represented by the following variable. */
3324 static htab_t state_table;
3326 /* Linked list of free 'state' structures to be recycled. The
3327 next_equiv_class_state pointer is borrowed for a free list. */
3328 static state_t first_free_state;
3330 static int curr_unique_state_num;
3332 #ifndef NDEBUG
3333 /* The following variables is maximal number of allocated nodes
3334 `state'. */
3335 static int allocated_states_num = 0;
3336 #endif
3338 /* Allocate new reservation set. */
3339 static reserv_sets_t
3340 alloc_empty_reserv_sets (void)
3342 reserv_sets_t result;
3344 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3345 result = (reserv_sets_t) obstack_base (&irp);
3346 obstack_finish (&irp);
3347 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3348 return result;
3351 /* Hash value of reservation set. */
3352 static unsigned
3353 reserv_sets_hash_value (reserv_sets_t reservs)
3355 set_el_t hash_value;
3356 unsigned result;
3357 int reservs_num, i;
3358 set_el_t *reserv_ptr;
3360 hash_value = 0;
3361 reservs_num = els_in_reservs;
3362 reserv_ptr = reservs;
3363 i = 0;
3364 while (reservs_num != 0)
3366 reservs_num--;
3367 hash_value += ((*reserv_ptr >> i)
3368 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3369 i++;
3370 if (i == sizeof (set_el_t) * CHAR_BIT)
3371 i = 0;
3372 reserv_ptr++;
3374 if (sizeof (set_el_t) <= sizeof (unsigned))
3375 return hash_value;
3376 result = 0;
3377 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3379 result += (unsigned) hash_value;
3380 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3382 return result;
3385 /* Comparison of given reservation sets. */
3386 static int
3387 reserv_sets_cmp (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3389 int reservs_num;
3390 set_el_t *reserv_ptr_1;
3391 set_el_t *reserv_ptr_2;
3393 gcc_assert (reservs_1 && reservs_2);
3394 reservs_num = els_in_reservs;
3395 reserv_ptr_1 = reservs_1;
3396 reserv_ptr_2 = reservs_2;
3397 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3399 reservs_num--;
3400 reserv_ptr_1++;
3401 reserv_ptr_2++;
3403 if (reservs_num == 0)
3404 return 0;
3405 else if (*reserv_ptr_1 < *reserv_ptr_2)
3406 return -1;
3407 else
3408 return 1;
3411 /* The function checks equality of the reservation sets. */
3412 static int
3413 reserv_sets_eq (reserv_sets_t reservs_1, reserv_sets_t reservs_2)
3415 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3418 /* Set up in the reservation set that unit with UNIT_NUM is used on
3419 CYCLE_NUM. */
3420 static void
3421 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3423 gcc_assert (cycle_num < max_cycles_num);
3424 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3425 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3428 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3429 used on CYCLE_NUM. */
3430 static int
3431 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3433 gcc_assert (cycle_num < max_cycles_num);
3434 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3435 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3438 /* The function checks that the reservation sets are intersected,
3439 i.e. there is a unit reservation on a cycle in both reservation
3440 sets. */
3441 static int
3442 reserv_sets_are_intersected (reserv_sets_t operand_1,
3443 reserv_sets_t operand_2)
3445 set_el_t *el_ptr_1;
3446 set_el_t *el_ptr_2;
3447 set_el_t *cycle_ptr_1;
3448 set_el_t *cycle_ptr_2;
3450 gcc_assert (operand_1 && operand_2);
3451 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3452 el_ptr_1 < operand_1 + els_in_reservs;
3453 el_ptr_1++, el_ptr_2++)
3454 if (*el_ptr_1 & *el_ptr_2)
3455 return 1;
3456 reserv_sets_or (temp_reserv, operand_1, operand_2);
3457 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3458 cycle_ptr_1 < operand_1 + els_in_reservs;
3459 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3461 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3462 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3463 el_ptr_1++, el_ptr_2++)
3464 if (*el_ptr_1 & *el_ptr_2)
3465 return 1;
3466 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3467 return 1;
3468 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3469 - operand_2),
3470 cycle_ptr_2, TRUE))
3471 return 1;
3472 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3473 return 1;
3474 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3475 cycle_ptr_2, TRUE))
3476 return 1;
3478 return 0;
3481 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3482 cpu cycle. The remaining bits of OPERAND (representing the last
3483 cycle unit reservations) are not changed. */
3484 static void
3485 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3487 int i;
3489 gcc_assert (result && operand && result != operand);
3490 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3491 result [i - els_in_cycle_reserv] = operand [i];
3494 /* OR of the reservation sets. */
3495 static void
3496 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3497 reserv_sets_t operand_2)
3499 set_el_t *el_ptr_1;
3500 set_el_t *el_ptr_2;
3501 set_el_t *result_set_el_ptr;
3503 gcc_assert (result && operand_1 && operand_2);
3504 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3505 el_ptr_1 < operand_1 + els_in_reservs;
3506 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3507 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3510 /* AND of the reservation sets. */
3511 static void
3512 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3513 reserv_sets_t operand_2)
3515 set_el_t *el_ptr_1;
3516 set_el_t *el_ptr_2;
3517 set_el_t *result_set_el_ptr;
3519 gcc_assert (result && operand_1 && operand_2);
3520 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3521 el_ptr_1 < operand_1 + els_in_reservs;
3522 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3523 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3526 /* The function outputs string representation of units reservation on
3527 cycle START_CYCLE in the reservation set. The function uses repeat
3528 construction if REPETITION_NUM > 1. */
3529 static void
3530 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3531 int repetition_num)
3533 int unit_num;
3534 int reserved_units_num;
3536 reserved_units_num = 0;
3537 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3538 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3539 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3540 reserved_units_num++;
3541 gcc_assert (repetition_num > 0);
3542 if (repetition_num != 1 && reserved_units_num > 1)
3543 fprintf (f, "(");
3544 reserved_units_num = 0;
3545 for (unit_num = 0;
3546 unit_num < description->units_num;
3547 unit_num++)
3548 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3549 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3551 if (reserved_units_num != 0)
3552 fprintf (f, "+");
3553 reserved_units_num++;
3554 fprintf (f, "%s", units_array [unit_num]->name);
3556 if (reserved_units_num == 0)
3557 fprintf (f, NOTHING_NAME);
3558 gcc_assert (repetition_num > 0);
3559 if (repetition_num != 1 && reserved_units_num > 1)
3560 fprintf (f, ")");
3561 if (repetition_num != 1)
3562 fprintf (f, "*%d", repetition_num);
3565 /* The function outputs string representation of units reservation in
3566 the reservation set. */
3567 static void
3568 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3570 int start_cycle = 0;
3571 int cycle;
3572 int repetition_num;
3574 repetition_num = 0;
3575 for (cycle = 0; cycle < max_cycles_num; cycle++)
3576 if (repetition_num == 0)
3578 repetition_num++;
3579 start_cycle = cycle;
3581 else if (memcmp
3582 ((char *) reservs + start_cycle * els_in_cycle_reserv
3583 * sizeof (set_el_t),
3584 (char *) reservs + cycle * els_in_cycle_reserv
3585 * sizeof (set_el_t),
3586 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3587 repetition_num++;
3588 else
3590 if (start_cycle != 0)
3591 fprintf (f, ", ");
3592 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3593 repetition_num = 1;
3594 start_cycle = cycle;
3596 if (start_cycle < max_cycles_num)
3598 if (start_cycle != 0)
3599 fprintf (f, ", ");
3600 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3604 /* The following function returns free node state for AUTOMATON. It
3605 may be new allocated node or node freed earlier. The function also
3606 allocates reservation set if WITH_RESERVS has nonzero value. */
3607 static state_t
3608 get_free_state (int with_reservs, automaton_t automaton)
3610 state_t result;
3612 gcc_assert (max_cycles_num > 0 && automaton);
3613 if (first_free_state)
3615 result = first_free_state;
3616 first_free_state = result->next_equiv_class_state;
3618 result->next_equiv_class_state = NULL;
3619 result->automaton = automaton;
3620 result->first_out_arc = NULL;
3621 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3622 result->it_was_placed_in_stack_for_DFA_forming = 0;
3623 result->component_states = NULL;
3624 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3626 else
3628 #ifndef NDEBUG
3629 allocated_states_num++;
3630 #endif
3631 result = create_node (sizeof (struct state));
3632 result->automaton = automaton;
3633 result->first_out_arc = NULL;
3634 result->unique_num = curr_unique_state_num;
3635 result->longest_path_length = UNDEFINED_LONGEST_PATH_LENGTH;
3636 curr_unique_state_num++;
3638 if (with_reservs)
3640 if (result->reservs == NULL)
3641 result->reservs = alloc_empty_reserv_sets ();
3642 else
3643 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3645 return result;
3648 /* The function frees node STATE. */
3649 static void
3650 free_state (state_t state)
3652 free_alt_states (state->component_states);
3653 state->next_equiv_class_state = first_free_state;
3654 first_free_state = state;
3657 /* Hash value of STATE. If STATE represents deterministic state it is
3658 simply hash value of the corresponding reservation set. Otherwise
3659 it is formed from hash values of the component deterministic
3660 states. One more key is order number of state automaton. */
3661 static hashval_t
3662 state_hash (const void *state)
3664 unsigned int hash_value;
3665 alt_state_t alt_state;
3667 if (((state_t) state)->component_states == NULL)
3668 hash_value = reserv_sets_hash_value (((state_t) state)->reservs);
3669 else
3671 hash_value = 0;
3672 for (alt_state = ((state_t) state)->component_states;
3673 alt_state != NULL;
3674 alt_state = alt_state->next_sorted_alt_state)
3675 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3676 | (hash_value << CHAR_BIT))
3677 + alt_state->state->unique_num);
3679 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3680 | (hash_value << CHAR_BIT))
3681 + ((state_t) state)->automaton->automaton_order_num);
3682 return hash_value;
3685 /* Return nonzero value if the states are the same. */
3686 static int
3687 state_eq_p (const void *state_1, const void *state_2)
3689 alt_state_t alt_state_1;
3690 alt_state_t alt_state_2;
3692 if (((state_t) state_1)->automaton != ((state_t) state_2)->automaton)
3693 return 0;
3694 else if (((state_t) state_1)->component_states == NULL
3695 && ((state_t) state_2)->component_states == NULL)
3696 return reserv_sets_eq (((state_t) state_1)->reservs,
3697 ((state_t) state_2)->reservs);
3698 else if (((state_t) state_1)->component_states != NULL
3699 && ((state_t) state_2)->component_states != NULL)
3701 for (alt_state_1 = ((state_t) state_1)->component_states,
3702 alt_state_2 = ((state_t) state_2)->component_states;
3703 alt_state_1 != NULL && alt_state_2 != NULL;
3704 alt_state_1 = alt_state_1->next_sorted_alt_state,
3705 alt_state_2 = alt_state_2->next_sorted_alt_state)
3706 /* All state in the list must be already in the hash table.
3707 Also the lists must be sorted. */
3708 if (alt_state_1->state != alt_state_2->state)
3709 return 0;
3710 return alt_state_1 == alt_state_2;
3712 else
3713 return 0;
3716 /* Insert STATE into the state table. */
3717 static state_t
3718 insert_state (state_t state)
3720 void **entry_ptr;
3722 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3723 if (*entry_ptr == NULL)
3724 *entry_ptr = (void *) state;
3725 return (state_t) *entry_ptr;
3728 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3729 deterministic STATE. */
3730 static void
3731 set_state_reserv (state_t state, int cycle_num, int unit_num)
3733 set_unit_reserv (state->reservs, cycle_num, unit_num);
3736 /* Return nonzero value if the deterministic states contains a
3737 reservation of the same cpu unit on the same cpu cycle. */
3738 static int
3739 intersected_state_reservs_p (state_t state1, state_t state2)
3741 gcc_assert (state1->automaton == state2->automaton);
3742 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3745 /* Return deterministic state (inserted into the table) which
3746 representing the automaton state which is union of reservations of
3747 the deterministic states masked by RESERVS. */
3748 static state_t
3749 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3751 state_t result;
3752 state_t state_in_table;
3754 gcc_assert (state1->automaton == state2->automaton);
3755 result = get_free_state (1, state1->automaton);
3756 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3757 reserv_sets_and (result->reservs, result->reservs, reservs);
3758 state_in_table = insert_state (result);
3759 if (result != state_in_table)
3761 free_state (result);
3762 result = state_in_table;
3764 return result;
3767 /* Return deterministic state (inserted into the table) which
3768 represent the automaton state is obtained from deterministic STATE
3769 by advancing cpu cycle and masking by RESERVS. */
3770 static state_t
3771 state_shift (state_t state, reserv_sets_t reservs)
3773 state_t result;
3774 state_t state_in_table;
3776 result = get_free_state (1, state->automaton);
3777 reserv_sets_shift (result->reservs, state->reservs);
3778 reserv_sets_and (result->reservs, result->reservs, reservs);
3779 state_in_table = insert_state (result);
3780 if (result != state_in_table)
3782 free_state (result);
3783 result = state_in_table;
3785 return result;
3788 /* Initialization of the abstract data. */
3789 static void
3790 initiate_states (void)
3792 decl_t decl;
3793 int i;
3795 if (description->units_num)
3796 units_array = XNEWVEC (unit_decl_t, description->units_num);
3797 else
3798 units_array = 0;
3800 for (i = 0; i < description->decls_num; i++)
3802 decl = description->decls [i];
3803 if (decl->mode == dm_unit)
3804 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3806 max_cycles_num = description->max_insn_reserv_cycles;
3807 els_in_cycle_reserv
3808 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3809 / (sizeof (set_el_t) * CHAR_BIT));
3810 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3811 curr_unique_state_num = 0;
3812 initiate_alt_states ();
3813 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3814 temp_reserv = alloc_empty_reserv_sets ();
3817 /* Finishing work with the abstract data. */
3818 static void
3819 finish_states (void)
3821 free (units_array);
3822 units_array = 0;
3823 htab_delete (state_table);
3824 first_free_state = NULL;
3825 finish_alt_states ();
3830 /* Abstract data `arcs'. */
3832 /* List of free arcs. */
3833 static arc_t first_free_arc;
3835 #ifndef NDEBUG
3836 /* The following variables is maximal number of allocated nodes
3837 `arc'. */
3838 static int allocated_arcs_num = 0;
3839 #endif
3841 /* The function frees node ARC. */
3842 static void
3843 free_arc (arc_t arc)
3845 arc->next_out_arc = first_free_arc;
3846 first_free_arc = arc;
3849 /* The function removes and frees ARC staring from FROM_STATE. */
3850 static void
3851 remove_arc (state_t from_state, arc_t arc)
3853 arc_t prev_arc;
3854 arc_t curr_arc;
3856 gcc_assert (arc);
3857 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3858 curr_arc != NULL;
3859 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3860 if (curr_arc == arc)
3861 break;
3862 gcc_assert (curr_arc);
3863 if (prev_arc == NULL)
3864 from_state->first_out_arc = arc->next_out_arc;
3865 else
3866 prev_arc->next_out_arc = arc->next_out_arc;
3867 from_state->num_out_arcs--;
3868 free_arc (arc);
3871 /* The functions returns arc with given characteristics (or NULL if
3872 the arc does not exist). */
3873 static arc_t
3874 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3876 arc_t arc;
3878 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3879 if (arc->to_state == to_state && arc->insn == insn)
3880 return arc;
3881 return NULL;
3884 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3885 The function returns added arc (or already existing arc). */
3886 static arc_t
3887 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3889 arc_t new_arc;
3891 new_arc = find_arc (from_state, to_state, ainsn);
3892 if (new_arc != NULL)
3893 return new_arc;
3894 if (first_free_arc == NULL)
3896 #ifndef NDEBUG
3897 allocated_arcs_num++;
3898 #endif
3899 new_arc = create_node (sizeof (struct arc));
3900 new_arc->to_state = NULL;
3901 new_arc->insn = NULL;
3902 new_arc->next_out_arc = NULL;
3904 else
3906 new_arc = first_free_arc;
3907 first_free_arc = first_free_arc->next_out_arc;
3909 new_arc->to_state = to_state;
3910 new_arc->insn = ainsn;
3911 ainsn->arc_exists_p = 1;
3912 new_arc->next_out_arc = from_state->first_out_arc;
3913 from_state->first_out_arc = new_arc;
3914 from_state->num_out_arcs++;
3915 new_arc->next_arc_marked_by_insn = NULL;
3916 return new_arc;
3919 /* The function returns the first arc starting from STATE. */
3920 static arc_t
3921 first_out_arc (state_t state)
3923 return state->first_out_arc;
3926 /* The function returns next out arc after ARC. */
3927 static arc_t
3928 next_out_arc (arc_t arc)
3930 return arc->next_out_arc;
3933 /* Initialization of the abstract data. */
3934 static void
3935 initiate_arcs (void)
3937 first_free_arc = NULL;
3940 /* Finishing work with the abstract data. */
3941 static void
3942 finish_arcs (void)
3948 /* Abstract data `automata lists'. */
3950 /* List of free states. */
3951 static automata_list_el_t first_free_automata_list_el;
3953 /* The list being formed. */
3954 static automata_list_el_t current_automata_list;
3956 /* Hash table of automata lists. */
3957 static htab_t automata_list_table;
3959 /* The following function returns free automata list el. It may be
3960 new allocated node or node freed earlier. */
3961 static automata_list_el_t
3962 get_free_automata_list_el (void)
3964 automata_list_el_t result;
3966 if (first_free_automata_list_el != NULL)
3968 result = first_free_automata_list_el;
3969 first_free_automata_list_el
3970 = first_free_automata_list_el->next_automata_list_el;
3972 else
3973 result = create_node (sizeof (struct automata_list_el));
3974 result->automaton = NULL;
3975 result->next_automata_list_el = NULL;
3976 return result;
3979 /* The function frees node AUTOMATA_LIST_EL. */
3980 static void
3981 free_automata_list_el (automata_list_el_t automata_list_el)
3983 if (automata_list_el == NULL)
3984 return;
3985 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3986 first_free_automata_list_el = automata_list_el;
3989 /* The function frees list AUTOMATA_LIST. */
3990 static void
3991 free_automata_list (automata_list_el_t automata_list)
3993 automata_list_el_t curr_automata_list_el;
3994 automata_list_el_t next_automata_list_el;
3996 for (curr_automata_list_el = automata_list;
3997 curr_automata_list_el != NULL;
3998 curr_automata_list_el = next_automata_list_el)
4000 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4001 free_automata_list_el (curr_automata_list_el);
4005 /* Hash value of AUTOMATA_LIST. */
4006 static hashval_t
4007 automata_list_hash (const void *automata_list)
4009 unsigned int hash_value;
4010 automata_list_el_t curr_automata_list_el;
4012 hash_value = 0;
4013 for (curr_automata_list_el = (automata_list_el_t) automata_list;
4014 curr_automata_list_el != NULL;
4015 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4016 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4017 | (hash_value << CHAR_BIT))
4018 + curr_automata_list_el->automaton->automaton_order_num);
4019 return hash_value;
4022 /* Return nonzero value if the automata_lists are the same. */
4023 static int
4024 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4026 automata_list_el_t automata_list_el_1;
4027 automata_list_el_t automata_list_el_2;
4029 for (automata_list_el_1 = (automata_list_el_t) automata_list_1,
4030 automata_list_el_2 = (automata_list_el_t) automata_list_2;
4031 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4032 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4033 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4034 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4035 return 0;
4036 return automata_list_el_1 == automata_list_el_2;
4039 /* Initialization of the abstract data. */
4040 static void
4041 initiate_automata_lists (void)
4043 first_free_automata_list_el = NULL;
4044 automata_list_table = htab_create (1500, automata_list_hash,
4045 automata_list_eq_p, (htab_del) 0);
4048 /* The following function starts new automata list and makes it the
4049 current one. */
4050 static void
4051 automata_list_start (void)
4053 current_automata_list = NULL;
4056 /* The following function adds AUTOMATON to the current list. */
4057 static void
4058 automata_list_add (automaton_t automaton)
4060 automata_list_el_t el;
4062 el = get_free_automata_list_el ();
4063 el->automaton = automaton;
4064 el->next_automata_list_el = current_automata_list;
4065 current_automata_list = el;
4068 /* The following function finishes forming the current list, inserts
4069 it into the table and returns it. */
4070 static automata_list_el_t
4071 automata_list_finish (void)
4073 void **entry_ptr;
4075 if (current_automata_list == NULL)
4076 return NULL;
4077 entry_ptr = htab_find_slot (automata_list_table,
4078 (void *) current_automata_list, 1);
4079 if (*entry_ptr == NULL)
4080 *entry_ptr = (void *) current_automata_list;
4081 else
4082 free_automata_list (current_automata_list);
4083 current_automata_list = NULL;
4084 return (automata_list_el_t) *entry_ptr;
4087 /* Finishing work with the abstract data. */
4088 static void
4089 finish_automata_lists (void)
4091 htab_delete (automata_list_table);
4096 /* The page contains abstract data for work with exclusion sets (see
4097 exclusion_set in file rtl.def). */
4099 /* The following variable refers to an exclusion set returned by
4100 get_excl_set. This is bit string of length equal to cpu units
4101 number. If exclusion set for given unit contains 1 for a unit,
4102 then simultaneous reservation of the units is prohibited. */
4103 static reserv_sets_t excl_set;
4105 /* The array contains exclusion sets for each unit. */
4106 static reserv_sets_t *unit_excl_set_table;
4108 /* The following function forms the array containing exclusion sets
4109 for each unit. */
4110 static void
4111 initiate_excl_sets (void)
4113 decl_t decl;
4114 reserv_sets_t unit_excl_set;
4115 unit_set_el_t el;
4116 int i;
4118 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4119 excl_set = (reserv_sets_t) obstack_base (&irp);
4120 obstack_finish (&irp);
4121 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4122 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4123 obstack_finish (&irp);
4124 /* Evaluate unit exclusion sets. */
4125 for (i = 0; i < description->decls_num; i++)
4127 decl = description->decls [i];
4128 if (decl->mode == dm_unit)
4130 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4131 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4132 obstack_finish (&irp);
4133 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4134 for (el = DECL_UNIT (decl)->excl_list;
4135 el != NULL;
4136 el = el->next_unit_set_el)
4138 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4139 el->unit_decl->in_set_p = TRUE;
4141 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4146 /* The function sets up and return EXCL_SET which is union of
4147 exclusion sets for each unit in IN_SET. */
4148 static reserv_sets_t
4149 get_excl_set (reserv_sets_t in_set)
4151 int excl_char_num;
4152 int chars_num;
4153 int i;
4154 int start_unit_num;
4155 int unit_num;
4157 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4158 memset (excl_set, 0, chars_num);
4159 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4160 if (((unsigned char *) in_set) [excl_char_num])
4161 for (i = CHAR_BIT - 1; i >= 0; i--)
4162 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4164 start_unit_num = excl_char_num * CHAR_BIT + i;
4165 if (start_unit_num >= description->units_num)
4166 return excl_set;
4167 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4169 excl_set [unit_num]
4170 |= unit_excl_set_table [start_unit_num] [unit_num];
4173 return excl_set;
4178 /* The page contains abstract data for work with presence/absence
4179 pattern sets (see presence_set/absence_set in file rtl.def). */
4181 /* The following arrays contain correspondingly presence, final
4182 presence, absence, and final absence patterns for each unit. */
4183 static pattern_reserv_t *unit_presence_set_table;
4184 static pattern_reserv_t *unit_final_presence_set_table;
4185 static pattern_reserv_t *unit_absence_set_table;
4186 static pattern_reserv_t *unit_final_absence_set_table;
4188 /* The following function forms list of reservation sets for given
4189 PATTERN_LIST. */
4190 static pattern_reserv_t
4191 form_reserv_sets_list (pattern_set_el_t pattern_list)
4193 pattern_set_el_t el;
4194 pattern_reserv_t first, curr, prev;
4195 int i;
4197 prev = first = NULL;
4198 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4200 curr = create_node (sizeof (struct pattern_reserv));
4201 curr->reserv = alloc_empty_reserv_sets ();
4202 curr->next_pattern_reserv = NULL;
4203 for (i = 0; i < el->units_num; i++)
4205 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4206 el->unit_decls [i]->in_set_p = TRUE;
4208 if (prev != NULL)
4209 prev->next_pattern_reserv = curr;
4210 else
4211 first = curr;
4212 prev = curr;
4214 return first;
4217 /* The following function forms the array containing presence and
4218 absence pattern sets for each unit. */
4219 static void
4220 initiate_presence_absence_pattern_sets (void)
4222 decl_t decl;
4223 int i;
4225 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4226 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4227 obstack_finish (&irp);
4228 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4229 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4230 obstack_finish (&irp);
4231 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4232 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4233 obstack_finish (&irp);
4234 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4235 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4236 obstack_finish (&irp);
4237 /* Evaluate unit presence/absence sets. */
4238 for (i = 0; i < description->decls_num; i++)
4240 decl = description->decls [i];
4241 if (decl->mode == dm_unit)
4243 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4244 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4245 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4246 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4247 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4248 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4249 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4250 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4255 /* The function checks that CHECKED_SET satisfies all presence pattern
4256 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4257 is ok. */
4258 static int
4259 check_presence_pattern_sets (reserv_sets_t checked_set,
4260 reserv_sets_t origional_set,
4261 int final_p)
4263 int char_num;
4264 int chars_num;
4265 int i;
4266 int start_unit_num;
4267 int unit_num;
4268 int presence_p;
4269 pattern_reserv_t pat_reserv;
4271 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4272 for (char_num = 0; char_num < chars_num; char_num++)
4273 if (((unsigned char *) origional_set) [char_num])
4274 for (i = CHAR_BIT - 1; i >= 0; i--)
4275 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4277 start_unit_num = char_num * CHAR_BIT + i;
4278 if (start_unit_num >= description->units_num)
4279 break;
4280 if ((final_p
4281 && unit_final_presence_set_table [start_unit_num] == NULL)
4282 || (!final_p
4283 && unit_presence_set_table [start_unit_num] == NULL))
4284 continue;
4285 presence_p = FALSE;
4286 for (pat_reserv = (final_p
4287 ? unit_final_presence_set_table [start_unit_num]
4288 : unit_presence_set_table [start_unit_num]);
4289 pat_reserv != NULL;
4290 pat_reserv = pat_reserv->next_pattern_reserv)
4292 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4293 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4294 != pat_reserv->reserv [unit_num])
4295 break;
4296 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4298 if (!presence_p)
4299 return FALSE;
4301 return TRUE;
4304 /* The function checks that CHECKED_SET satisfies all absence pattern
4305 sets for units in ORIGIONAL_SET. The function returns TRUE if it
4306 is ok. */
4307 static int
4308 check_absence_pattern_sets (reserv_sets_t checked_set,
4309 reserv_sets_t origional_set,
4310 int final_p)
4312 int char_num;
4313 int chars_num;
4314 int i;
4315 int start_unit_num;
4316 int unit_num;
4317 pattern_reserv_t pat_reserv;
4319 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4320 for (char_num = 0; char_num < chars_num; char_num++)
4321 if (((unsigned char *) origional_set) [char_num])
4322 for (i = CHAR_BIT - 1; i >= 0; i--)
4323 if ((((unsigned char *) origional_set) [char_num] >> i) & 1)
4325 start_unit_num = char_num * CHAR_BIT + i;
4326 if (start_unit_num >= description->units_num)
4327 break;
4328 for (pat_reserv = (final_p
4329 ? unit_final_absence_set_table [start_unit_num]
4330 : unit_absence_set_table [start_unit_num]);
4331 pat_reserv != NULL;
4332 pat_reserv = pat_reserv->next_pattern_reserv)
4334 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4335 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4336 != pat_reserv->reserv [unit_num]
4337 && pat_reserv->reserv [unit_num])
4338 break;
4339 if (unit_num >= els_in_cycle_reserv)
4340 return FALSE;
4343 return TRUE;
4348 /* This page contains code for transformation of original reservations
4349 described in .md file. The main goal of transformations is
4350 simplifying reservation and lifting up all `|' on the top of IR
4351 reservation representation. */
4354 /* The following function makes copy of IR representation of
4355 reservation. The function also substitutes all reservations
4356 defined by define_reservation by corresponding value during making
4357 the copy. */
4358 static regexp_t
4359 copy_insn_regexp (regexp_t regexp)
4361 regexp_t result;
4362 int i;
4364 switch (regexp->mode)
4366 case rm_reserv:
4367 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4368 break;
4370 case rm_unit:
4371 result = copy_node (regexp, sizeof (struct regexp));
4372 break;
4374 case rm_repeat:
4375 result = copy_node (regexp, sizeof (struct regexp));
4376 REGEXP_REPEAT (result)->regexp
4377 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4378 break;
4380 case rm_sequence:
4381 result = copy_node (regexp,
4382 sizeof (struct regexp) + sizeof (regexp_t)
4383 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4384 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4385 REGEXP_SEQUENCE (result)->regexps [i]
4386 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4387 break;
4389 case rm_allof:
4390 result = copy_node (regexp,
4391 sizeof (struct regexp) + sizeof (regexp_t)
4392 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4393 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4394 REGEXP_ALLOF (result)->regexps [i]
4395 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4396 break;
4398 case rm_oneof:
4399 result = copy_node (regexp,
4400 sizeof (struct regexp) + sizeof (regexp_t)
4401 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4402 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4403 REGEXP_ONEOF (result)->regexps [i]
4404 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4405 break;
4407 case rm_nothing:
4408 result = copy_node (regexp, sizeof (struct regexp));
4409 break;
4411 default:
4412 gcc_unreachable ();
4414 return result;
4417 /* The following variable is set up 1 if a transformation has been
4418 applied. */
4419 static int regexp_transformed_p;
4421 /* The function makes transformation
4422 A*N -> A, A, ... */
4423 static regexp_t
4424 transform_1 (regexp_t regexp)
4426 int i;
4427 int repeat_num;
4428 regexp_t operand;
4429 pos_t pos;
4431 if (regexp->mode == rm_repeat)
4433 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4434 gcc_assert (repeat_num > 1);
4435 operand = REGEXP_REPEAT (regexp)->regexp;
4436 pos = regexp->mode;
4437 regexp = create_node (sizeof (struct regexp) + sizeof (regexp_t)
4438 * (repeat_num - 1));
4439 regexp->mode = rm_sequence;
4440 regexp->pos = pos;
4441 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4442 for (i = 0; i < repeat_num; i++)
4443 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4444 regexp_transformed_p = 1;
4446 return regexp;
4449 /* The function makes transformations
4450 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4451 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4452 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4453 static regexp_t
4454 transform_2 (regexp_t regexp)
4456 if (regexp->mode == rm_sequence)
4458 regexp_t sequence = NULL;
4459 regexp_t result;
4460 int sequence_index = 0;
4461 int i, j;
4463 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4464 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4466 sequence_index = i;
4467 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4468 break;
4470 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4472 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4473 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4474 result = create_node (sizeof (struct regexp)
4475 + sizeof (regexp_t)
4476 * (REGEXP_SEQUENCE (regexp)->regexps_num
4477 + REGEXP_SEQUENCE (sequence)->regexps_num
4478 - 2));
4479 result->mode = rm_sequence;
4480 result->pos = regexp->pos;
4481 REGEXP_SEQUENCE (result)->regexps_num
4482 = (REGEXP_SEQUENCE (regexp)->regexps_num
4483 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4484 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4485 if (i < sequence_index)
4486 REGEXP_SEQUENCE (result)->regexps [i]
4487 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4488 else if (i > sequence_index)
4489 REGEXP_SEQUENCE (result)->regexps
4490 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4491 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4492 else
4493 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4494 REGEXP_SEQUENCE (result)->regexps [i + j]
4495 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4496 regexp_transformed_p = 1;
4497 regexp = result;
4500 else if (regexp->mode == rm_allof)
4502 regexp_t allof = NULL;
4503 regexp_t result;
4504 int allof_index = 0;
4505 int i, j;
4507 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4508 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4510 allof_index = i;
4511 allof = REGEXP_ALLOF (regexp)->regexps [i];
4512 break;
4514 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4516 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4517 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4518 result = create_node (sizeof (struct regexp)
4519 + sizeof (regexp_t)
4520 * (REGEXP_ALLOF (regexp)->regexps_num
4521 + REGEXP_ALLOF (allof)->regexps_num - 2));
4522 result->mode = rm_allof;
4523 result->pos = regexp->pos;
4524 REGEXP_ALLOF (result)->regexps_num
4525 = (REGEXP_ALLOF (regexp)->regexps_num
4526 + REGEXP_ALLOF (allof)->regexps_num - 1);
4527 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4528 if (i < allof_index)
4529 REGEXP_ALLOF (result)->regexps [i]
4530 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4531 else if (i > allof_index)
4532 REGEXP_ALLOF (result)->regexps
4533 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4534 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4535 else
4536 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4537 REGEXP_ALLOF (result)->regexps [i + j]
4538 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4539 regexp_transformed_p = 1;
4540 regexp = result;
4543 else if (regexp->mode == rm_oneof)
4545 regexp_t oneof = NULL;
4546 regexp_t result;
4547 int oneof_index = 0;
4548 int i, j;
4550 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4551 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4553 oneof_index = i;
4554 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4555 break;
4557 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4559 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4560 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4561 result = create_node (sizeof (struct regexp)
4562 + sizeof (regexp_t)
4563 * (REGEXP_ONEOF (regexp)->regexps_num
4564 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4565 result->mode = rm_oneof;
4566 result->pos = regexp->pos;
4567 REGEXP_ONEOF (result)->regexps_num
4568 = (REGEXP_ONEOF (regexp)->regexps_num
4569 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4570 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4571 if (i < oneof_index)
4572 REGEXP_ONEOF (result)->regexps [i]
4573 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4574 else if (i > oneof_index)
4575 REGEXP_ONEOF (result)->regexps
4576 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4577 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4578 else
4579 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4580 REGEXP_ONEOF (result)->regexps [i + j]
4581 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4582 regexp_transformed_p = 1;
4583 regexp = result;
4586 return regexp;
4589 /* The function makes transformations
4590 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4591 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4592 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4593 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4594 static regexp_t
4595 transform_3 (regexp_t regexp)
4597 if (regexp->mode == rm_sequence)
4599 regexp_t oneof = NULL;
4600 int oneof_index = 0;
4601 regexp_t result;
4602 regexp_t sequence;
4603 int i, j;
4605 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4606 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4608 oneof_index = i;
4609 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4610 break;
4612 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4614 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4615 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4616 result = create_node (sizeof (struct regexp)
4617 + sizeof (regexp_t)
4618 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4619 result->mode = rm_oneof;
4620 result->pos = regexp->pos;
4621 REGEXP_ONEOF (result)->regexps_num
4622 = REGEXP_ONEOF (oneof)->regexps_num;
4623 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4625 sequence
4626 = create_node (sizeof (struct regexp)
4627 + sizeof (regexp_t)
4628 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4629 sequence->mode = rm_sequence;
4630 sequence->pos = regexp->pos;
4631 REGEXP_SEQUENCE (sequence)->regexps_num
4632 = REGEXP_SEQUENCE (regexp)->regexps_num;
4633 REGEXP_ONEOF (result)->regexps [i] = sequence;
4634 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4635 if (j != oneof_index)
4636 REGEXP_SEQUENCE (sequence)->regexps [j]
4637 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4638 else
4639 REGEXP_SEQUENCE (sequence)->regexps [j]
4640 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4642 regexp_transformed_p = 1;
4643 regexp = result;
4646 else if (regexp->mode == rm_allof)
4648 regexp_t oneof = NULL;
4649 regexp_t seq;
4650 int oneof_index = 0;
4651 int max_seq_length, allof_length;
4652 regexp_t result;
4653 regexp_t allof = NULL;
4654 regexp_t allof_op = NULL;
4655 int i, j;
4657 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4658 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4660 oneof_index = i;
4661 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4662 break;
4664 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4666 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4667 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4668 result = create_node (sizeof (struct regexp)
4669 + sizeof (regexp_t)
4670 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4671 result->mode = rm_oneof;
4672 result->pos = regexp->pos;
4673 REGEXP_ONEOF (result)->regexps_num
4674 = REGEXP_ONEOF (oneof)->regexps_num;
4675 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4677 allof
4678 = create_node (sizeof (struct regexp)
4679 + sizeof (regexp_t)
4680 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4681 allof->mode = rm_allof;
4682 allof->pos = regexp->pos;
4683 REGEXP_ALLOF (allof)->regexps_num
4684 = REGEXP_ALLOF (regexp)->regexps_num;
4685 REGEXP_ONEOF (result)->regexps [i] = allof;
4686 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4687 if (j != oneof_index)
4688 REGEXP_ALLOF (allof)->regexps [j]
4689 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4690 else
4691 REGEXP_ALLOF (allof)->regexps [j]
4692 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4694 regexp_transformed_p = 1;
4695 regexp = result;
4697 max_seq_length = 0;
4698 if (regexp->mode == rm_allof)
4699 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4701 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4703 case rm_sequence:
4704 seq = REGEXP_ALLOF (regexp)->regexps [i];
4705 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4706 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4707 break;
4709 case rm_unit:
4710 case rm_nothing:
4711 break;
4713 default:
4714 max_seq_length = 0;
4715 goto break_for;
4718 break_for:
4719 if (max_seq_length != 0)
4721 gcc_assert (max_seq_length != 1
4722 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4723 result = create_node (sizeof (struct regexp)
4724 + sizeof (regexp_t) * (max_seq_length - 1));
4725 result->mode = rm_sequence;
4726 result->pos = regexp->pos;
4727 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4728 for (i = 0; i < max_seq_length; i++)
4730 allof_length = 0;
4731 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4732 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4734 case rm_sequence:
4735 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4736 ->regexps [j])->regexps_num))
4738 allof_op
4739 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4740 ->regexps [j])
4741 ->regexps [i]);
4742 allof_length++;
4744 break;
4745 case rm_unit:
4746 case rm_nothing:
4747 if (i == 0)
4749 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4750 allof_length++;
4752 break;
4753 default:
4754 break;
4757 if (allof_length == 1)
4758 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4759 else
4761 allof = create_node (sizeof (struct regexp)
4762 + sizeof (regexp_t)
4763 * (allof_length - 1));
4764 allof->mode = rm_allof;
4765 allof->pos = regexp->pos;
4766 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4767 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4768 allof_length = 0;
4769 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4770 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4771 && (i <
4772 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4773 ->regexps [j])->regexps_num)))
4775 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4776 ->regexps [j])
4777 ->regexps [i]);
4778 REGEXP_ALLOF (allof)->regexps [allof_length]
4779 = allof_op;
4780 allof_length++;
4782 else if (i == 0
4783 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4784 == rm_unit
4785 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4786 == rm_nothing)))
4788 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4789 REGEXP_ALLOF (allof)->regexps [allof_length]
4790 = allof_op;
4791 allof_length++;
4795 regexp_transformed_p = 1;
4796 regexp = result;
4799 return regexp;
4802 /* The function traverses IR of reservation and applies transformations
4803 implemented by FUNC. */
4804 static regexp_t
4805 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4807 int i;
4809 switch (regexp->mode)
4811 case rm_sequence:
4812 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4813 REGEXP_SEQUENCE (regexp)->regexps [i]
4814 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4815 func);
4816 break;
4818 case rm_allof:
4819 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4820 REGEXP_ALLOF (regexp)->regexps [i]
4821 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4822 break;
4824 case rm_oneof:
4825 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4826 REGEXP_ONEOF (regexp)->regexps [i]
4827 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4828 break;
4830 case rm_repeat:
4831 REGEXP_REPEAT (regexp)->regexp
4832 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4833 break;
4835 case rm_nothing:
4836 case rm_unit:
4837 break;
4839 default:
4840 gcc_unreachable ();
4842 return (*func) (regexp);
4845 /* The function applies all transformations for IR representation of
4846 reservation REGEXP. */
4847 static regexp_t
4848 transform_regexp (regexp_t regexp)
4850 regexp = regexp_transform_func (regexp, transform_1);
4853 regexp_transformed_p = 0;
4854 regexp = regexp_transform_func (regexp, transform_2);
4855 regexp = regexp_transform_func (regexp, transform_3);
4857 while (regexp_transformed_p);
4858 return regexp;
4861 /* The function applies all transformations for reservations of all
4862 insn declarations. */
4863 static void
4864 transform_insn_regexps (void)
4866 decl_t decl;
4867 int i;
4869 transform_time = create_ticker ();
4870 add_advance_cycle_insn_decl ();
4871 if (progress_flag)
4872 fprintf (stderr, "Reservation transformation...");
4873 for (i = 0; i < description->decls_num; i++)
4875 decl = description->decls [i];
4876 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4877 DECL_INSN_RESERV (decl)->transformed_regexp
4878 = transform_regexp (copy_insn_regexp
4879 (DECL_INSN_RESERV (decl)->regexp));
4881 if (progress_flag)
4882 fprintf (stderr, "done\n");
4883 ticker_off (&transform_time);
4888 /* The following variable value is TRUE if the first annotated message
4889 about units to automata distribution has been output. */
4890 static int annotation_message_reported_p;
4892 /* The following structure describes usage of a unit in a reservation. */
4893 struct unit_usage
4895 unit_decl_t unit_decl;
4896 /* The following forms a list of units used on the same cycle in the
4897 same alternative. */
4898 struct unit_usage *next;
4900 typedef struct unit_usage *unit_usage_t;
4902 DEF_VEC_P(unit_usage_t);
4903 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4905 /* Obstack for unit_usage structures. */
4906 static struct obstack unit_usages;
4908 /* VLA for representation of array of pointers to unit usage
4909 structures. There is an element for each combination of
4910 (alternative number, cycle). Unit usages on given cycle in
4911 alternative with given number are referred through element with
4912 index equals to the cycle * number of all alternatives in the regexp
4913 + the alternative number. */
4914 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4916 /* The following function creates the structure unit_usage for UNIT on
4917 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4918 accessed through cycle_alt_unit_usages. */
4919 static void
4920 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4921 int alt_num)
4923 size_t length;
4924 unit_decl_t unit_decl;
4925 unit_usage_t unit_usage_ptr;
4926 int index;
4928 gcc_assert (regexp && regexp->mode == rm_oneof
4929 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4930 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4932 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4933 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4934 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4936 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4937 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4938 obstack_finish (&unit_usages);
4939 unit_usage_ptr->unit_decl = unit_decl;
4940 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4941 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4942 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4943 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4946 /* The function processes given REGEXP to find units with the wrong
4947 distribution. */
4948 static void
4949 check_regexp_units_distribution (const char *insn_reserv_name,
4950 regexp_t regexp)
4952 int i, j, k, cycle;
4953 regexp_t seq, allof, unit;
4954 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4956 if (regexp == NULL || regexp->mode != rm_oneof)
4957 return;
4958 /* Store all unit usages in the regexp: */
4959 obstack_init (&unit_usages);
4960 cycle_alt_unit_usages = 0;
4962 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4964 seq = REGEXP_ONEOF (regexp)->regexps [i];
4965 switch (seq->mode)
4967 case rm_sequence:
4968 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4970 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4971 switch (allof->mode)
4973 case rm_allof:
4974 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4976 unit = REGEXP_ALLOF (allof)->regexps [k];
4977 if (unit->mode == rm_unit)
4978 store_alt_unit_usage (regexp, unit, j, i);
4979 else
4980 gcc_assert (unit->mode == rm_nothing);
4982 break;
4984 case rm_unit:
4985 store_alt_unit_usage (regexp, allof, j, i);
4986 break;
4988 case rm_nothing:
4989 break;
4991 default:
4992 gcc_unreachable ();
4995 break;
4997 case rm_allof:
4998 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5000 unit = REGEXP_ALLOF (seq)->regexps [k];
5001 switch (unit->mode)
5003 case rm_unit:
5004 store_alt_unit_usage (regexp, unit, 0, i);
5005 break;
5007 case rm_nothing:
5008 break;
5010 default:
5011 gcc_unreachable ();
5014 break;
5016 case rm_unit:
5017 store_alt_unit_usage (regexp, seq, 0, i);
5018 break;
5020 case rm_nothing:
5021 break;
5023 default:
5024 gcc_unreachable ();
5027 /* Check distribution: */
5028 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5030 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5031 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5032 unit_usage_ptr != NULL;
5033 unit_usage_ptr = unit_usage_ptr->next)
5034 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5036 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5037 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5038 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5039 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5040 k++)
5042 for (other_unit_usage_ptr
5043 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5044 other_unit_usage_ptr != NULL;
5045 other_unit_usage_ptr = other_unit_usage_ptr->next)
5046 if (unit_usage_ptr->unit_decl->automaton_decl
5047 == other_unit_usage_ptr->unit_decl->automaton_decl)
5048 break;
5049 if (other_unit_usage_ptr == NULL
5050 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5051 != NULL))
5052 break;
5054 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5055 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5057 if (!annotation_message_reported_p)
5059 fprintf (stderr, "\n");
5060 error ("The following units do not satisfy units-automata distribution rule");
5061 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5062 annotation_message_reported_p = TRUE;
5064 error ("Unit %s, reserv. %s, cycle %d",
5065 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5066 cycle);
5070 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5071 obstack_free (&unit_usages, NULL);
5074 /* The function finds units which violates units to automata
5075 distribution rule. If the units exist, report about them. */
5076 static void
5077 check_unit_distributions_to_automata (void)
5079 decl_t decl;
5080 int i;
5082 if (progress_flag)
5083 fprintf (stderr, "Check unit distributions to automata...");
5084 annotation_message_reported_p = FALSE;
5085 for (i = 0; i < description->decls_num; i++)
5087 decl = description->decls [i];
5088 if (decl->mode == dm_insn_reserv)
5089 check_regexp_units_distribution
5090 (DECL_INSN_RESERV (decl)->name,
5091 DECL_INSN_RESERV (decl)->transformed_regexp);
5093 if (progress_flag)
5094 fprintf (stderr, "done\n");
5099 /* The page contains code for building alt_states (see comments for
5100 IR) describing all possible insns reservations of an automaton. */
5102 /* Current state being formed for which the current alt_state
5103 refers. */
5104 static state_t state_being_formed;
5106 /* Current alt_state being formed. */
5107 static alt_state_t alt_state_being_formed;
5109 /* This recursive function processes `,' and units in reservation
5110 REGEXP for forming alt_states of AUTOMATON. It is believed that
5111 CURR_CYCLE is start cycle of all reservation REGEXP. */
5112 static int
5113 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5114 int curr_cycle)
5116 int i;
5118 if (regexp == NULL)
5119 return curr_cycle;
5121 switch (regexp->mode)
5123 case rm_unit:
5124 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5125 == automaton->automaton_order_num)
5126 set_state_reserv (state_being_formed, curr_cycle,
5127 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5128 return curr_cycle;
5130 case rm_sequence:
5131 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5132 curr_cycle
5133 = process_seq_for_forming_states
5134 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5135 return curr_cycle;
5137 case rm_allof:
5139 int finish_cycle = 0;
5140 int cycle;
5142 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5144 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5145 ->regexps [i],
5146 automaton, curr_cycle);
5147 if (finish_cycle < cycle)
5148 finish_cycle = cycle;
5150 return finish_cycle;
5153 case rm_nothing:
5154 return curr_cycle;
5156 default:
5157 gcc_unreachable ();
5161 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5162 inserts alt_state into the table. */
5163 static void
5164 finish_forming_alt_state (alt_state_t alt_state,
5165 automaton_t automaton ATTRIBUTE_UNUSED)
5167 state_t state_in_table;
5168 state_t corresponding_state;
5170 corresponding_state = alt_state->state;
5171 state_in_table = insert_state (corresponding_state);
5172 if (state_in_table != corresponding_state)
5174 free_state (corresponding_state);
5175 alt_state->state = state_in_table;
5179 /* The following variable value is current automaton insn for whose
5180 reservation the alt states are created. */
5181 static ainsn_t curr_ainsn;
5183 /* This recursive function processes `|' in reservation REGEXP for
5184 forming alt_states of AUTOMATON. List of the alt states should
5185 have the same order as in the description. */
5186 static void
5187 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5188 int inside_oneof_p)
5190 int i;
5192 if (regexp->mode != rm_oneof)
5194 alt_state_being_formed = get_free_alt_state ();
5195 state_being_formed = get_free_state (1, automaton);
5196 alt_state_being_formed->state = state_being_formed;
5197 /* We inserts in reverse order but we process alternatives also
5198 in reverse order. So we have the same order of alternative
5199 as in the description. */
5200 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5201 curr_ainsn->alt_states = alt_state_being_formed;
5202 (void) process_seq_for_forming_states (regexp, automaton, 0);
5203 finish_forming_alt_state (alt_state_being_formed, automaton);
5205 else
5207 gcc_assert (!inside_oneof_p);
5208 /* We processes it in reverse order to get list with the same
5209 order as in the description. See also the previous
5210 commentary. */
5211 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5212 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5213 automaton, 1);
5217 /* Create nodes alt_state for all AUTOMATON insns. */
5218 static void
5219 create_alt_states (automaton_t automaton)
5221 struct insn_reserv_decl *reserv_decl;
5223 for (curr_ainsn = automaton->ainsn_list;
5224 curr_ainsn != NULL;
5225 curr_ainsn = curr_ainsn->next_ainsn)
5227 reserv_decl = curr_ainsn->insn_reserv_decl;
5228 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5230 curr_ainsn->alt_states = NULL;
5231 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5232 automaton, 0);
5233 curr_ainsn->sorted_alt_states
5234 = uniq_sort_alt_states (curr_ainsn->alt_states);
5241 /* The page contains major code for building DFA(s) for fast pipeline
5242 hazards recognition. */
5244 /* The function forms list of ainsns of AUTOMATON with the same
5245 reservation. */
5247 static void
5248 form_ainsn_with_same_reservs (automaton_t automaton)
5250 ainsn_t curr_ainsn;
5251 size_t i;
5252 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5254 for (curr_ainsn = automaton->ainsn_list;
5255 curr_ainsn != NULL;
5256 curr_ainsn = curr_ainsn->next_ainsn)
5257 if (curr_ainsn->insn_reserv_decl
5258 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5260 curr_ainsn->next_same_reservs_insn = NULL;
5261 curr_ainsn->first_insn_with_same_reservs = 1;
5263 else
5265 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5266 if (alt_states_eq
5267 (curr_ainsn->sorted_alt_states,
5268 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5269 break;
5270 curr_ainsn->next_same_reservs_insn = NULL;
5271 if (i < VEC_length (ainsn_t, last_insns))
5273 curr_ainsn->first_insn_with_same_reservs = 0;
5274 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5275 = curr_ainsn;
5276 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5278 else
5280 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5281 curr_ainsn->first_insn_with_same_reservs = 1;
5284 VEC_free (ainsn_t,heap, last_insns);
5287 /* Forming unit reservations which can affect creating the automaton
5288 states achieved from a given state. It permits to build smaller
5289 automata in many cases. We would have the same automata after
5290 the minimization without such optimization, but the automaton
5291 right after the building could be huge. So in other words, usage
5292 of reservs_matter means some minimization during building the
5293 automaton. */
5294 static reserv_sets_t
5295 form_reservs_matter (automaton_t automaton)
5297 int cycle, unit;
5298 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5300 for (cycle = 0; cycle < max_cycles_num; cycle++)
5301 for (unit = 0; unit < description->units_num; unit++)
5302 if (units_array [unit]->automaton_decl
5303 == automaton->corresponding_automaton_decl
5304 && (cycle >= units_array [unit]->min_occ_cycle_num
5305 /* We can not remove queried unit from reservations. */
5306 || units_array [unit]->query_p
5307 /* We can not remove units which are used
5308 `exclusion_set', `presence_set',
5309 `final_presence_set', `absence_set', and
5310 `final_absence_set'. */
5311 || units_array [unit]->in_set_p))
5312 set_unit_reserv (reservs_matter, cycle, unit);
5313 return reservs_matter;
5316 /* The following function creates all states of nondeterministic AUTOMATON. */
5317 static void
5318 make_automaton (automaton_t automaton)
5320 ainsn_t ainsn;
5321 struct insn_reserv_decl *insn_reserv_decl;
5322 alt_state_t alt_state;
5323 state_t state;
5324 state_t start_state;
5325 state_t state2;
5326 ainsn_t advance_cycle_ainsn;
5327 arc_t added_arc;
5328 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5329 int states_n;
5330 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5332 /* Create the start state (empty state). */
5333 start_state = insert_state (get_free_state (1, automaton));
5334 automaton->start_state = start_state;
5335 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5336 VEC_safe_push (state_t,heap, state_stack, start_state);
5337 states_n = 1;
5338 while (VEC_length (state_t, state_stack) != 0)
5340 state = VEC_pop (state_t, state_stack);
5341 advance_cycle_ainsn = NULL;
5342 for (ainsn = automaton->ainsn_list;
5343 ainsn != NULL;
5344 ainsn = ainsn->next_ainsn)
5345 if (ainsn->first_insn_with_same_reservs)
5347 insn_reserv_decl = ainsn->insn_reserv_decl;
5348 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5350 /* We process alt_states in the same order as they are
5351 present in the description. */
5352 added_arc = NULL;
5353 for (alt_state = ainsn->alt_states;
5354 alt_state != NULL;
5355 alt_state = alt_state->next_alt_state)
5357 state2 = alt_state->state;
5358 if (!intersected_state_reservs_p (state, state2))
5360 state2 = states_union (state, state2, reservs_matter);
5361 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5363 state2->it_was_placed_in_stack_for_NDFA_forming
5364 = 1;
5365 VEC_safe_push (state_t,heap, state_stack, state2);
5366 states_n++;
5367 if (progress_flag && states_n % 100 == 0)
5368 fprintf (stderr, ".");
5370 added_arc = add_arc (state, state2, ainsn);
5371 if (!ndfa_flag)
5372 break;
5375 if (!ndfa_flag && added_arc != NULL)
5377 for (alt_state = ainsn->alt_states;
5378 alt_state != NULL;
5379 alt_state = alt_state->next_alt_state)
5380 state2 = alt_state->state;
5383 else
5384 advance_cycle_ainsn = ainsn;
5386 /* Add transition to advance cycle. */
5387 state2 = state_shift (state, reservs_matter);
5388 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5390 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5391 VEC_safe_push (state_t,heap, state_stack, state2);
5392 states_n++;
5393 if (progress_flag && states_n % 100 == 0)
5394 fprintf (stderr, ".");
5396 gcc_assert (advance_cycle_ainsn);
5397 add_arc (state, state2, advance_cycle_ainsn);
5399 VEC_free (state_t,heap, state_stack);
5402 /* Foms lists of all arcs of STATE marked by the same ainsn. */
5403 static void
5404 form_arcs_marked_by_insn (state_t state)
5406 decl_t decl;
5407 arc_t arc;
5408 int i;
5410 for (i = 0; i < description->decls_num; i++)
5412 decl = description->decls [i];
5413 if (decl->mode == dm_insn_reserv)
5414 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5416 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5418 gcc_assert (arc->insn);
5419 arc->next_arc_marked_by_insn
5420 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5421 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5425 /* The function creates composed state (see comments for IR) from
5426 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5427 same insn. If the composed state is not in STATE_STACK yet, it is
5428 pushed into STATE_STACK. */
5430 static int
5431 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5432 VEC(state_t,heap) **state_stack)
5434 state_t state;
5435 alt_state_t alt_state, curr_alt_state;
5436 alt_state_t new_alt_state;
5437 arc_t curr_arc;
5438 arc_t next_arc;
5439 state_t state_in_table;
5440 state_t temp_state;
5441 alt_state_t canonical_alt_states_list;
5442 int alts_number;
5443 int new_state_p = 0;
5445 if (arcs_marked_by_insn == NULL)
5446 return new_state_p;
5447 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5448 state = arcs_marked_by_insn->to_state;
5449 else
5451 gcc_assert (ndfa_flag);
5452 /* Create composed state. */
5453 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5454 curr_alt_state = NULL;
5455 for (curr_arc = arcs_marked_by_insn;
5456 curr_arc != NULL;
5457 curr_arc = curr_arc->next_arc_marked_by_insn)
5458 if (curr_arc->to_state->component_states == NULL)
5460 new_alt_state = get_free_alt_state ();
5461 new_alt_state->next_alt_state = curr_alt_state;
5462 new_alt_state->state = curr_arc->to_state;
5463 curr_alt_state = new_alt_state;
5465 else
5466 for (alt_state = curr_arc->to_state->component_states;
5467 alt_state != NULL;
5468 alt_state = alt_state->next_sorted_alt_state)
5470 new_alt_state = get_free_alt_state ();
5471 new_alt_state->next_alt_state = curr_alt_state;
5472 new_alt_state->state = alt_state->state;
5473 gcc_assert (!alt_state->state->component_states);
5474 curr_alt_state = new_alt_state;
5476 /* There are not identical sets in the alt state list. */
5477 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5478 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5480 temp_state = state;
5481 state = canonical_alt_states_list->state;
5482 free_state (temp_state);
5484 else
5486 state->component_states = canonical_alt_states_list;
5487 state_in_table = insert_state (state);
5488 if (state_in_table != state)
5490 gcc_assert
5491 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5492 free_state (state);
5493 state = state_in_table;
5495 else
5497 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5498 new_state_p = 1;
5499 for (curr_alt_state = state->component_states;
5500 curr_alt_state != NULL;
5501 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5502 for (curr_arc = first_out_arc (curr_alt_state->state);
5503 curr_arc != NULL;
5504 curr_arc = next_out_arc (curr_arc))
5505 add_arc (state, curr_arc->to_state, curr_arc->insn);
5507 arcs_marked_by_insn->to_state = state;
5508 for (alts_number = 0,
5509 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5510 curr_arc != NULL;
5511 curr_arc = next_arc)
5513 next_arc = curr_arc->next_arc_marked_by_insn;
5514 remove_arc (original_state, curr_arc);
5515 alts_number++;
5519 if (!state->it_was_placed_in_stack_for_DFA_forming)
5521 state->it_was_placed_in_stack_for_DFA_forming = 1;
5522 VEC_safe_push (state_t,heap, *state_stack, state);
5524 return new_state_p;
5527 /* The function transforms nondeterministic AUTOMATON into
5528 deterministic. */
5530 static void
5531 NDFA_to_DFA (automaton_t automaton)
5533 state_t start_state;
5534 state_t state;
5535 decl_t decl;
5536 VEC(state_t,heap) *state_stack;
5537 int i;
5538 int states_n;
5540 state_stack = VEC_alloc (state_t,heap, 0);
5542 /* Create the start state (empty state). */
5543 start_state = automaton->start_state;
5544 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5545 VEC_safe_push (state_t,heap, state_stack, start_state);
5546 states_n = 1;
5547 while (VEC_length (state_t, state_stack) != 0)
5549 state = VEC_pop (state_t, state_stack);
5550 form_arcs_marked_by_insn (state);
5551 for (i = 0; i < description->decls_num; i++)
5553 decl = description->decls [i];
5554 if (decl->mode == dm_insn_reserv
5555 && create_composed_state
5556 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5557 &state_stack))
5559 states_n++;
5560 if (progress_flag && states_n % 100 == 0)
5561 fprintf (stderr, ".");
5565 VEC_free (state_t,heap, state_stack);
5568 /* The following variable value is current number (1, 2, ...) of passing
5569 graph of states. */
5570 static int curr_state_graph_pass_num;
5572 /* This recursive function passes all states achieved from START_STATE
5573 and applies APPLIED_FUNC to them. */
5574 static void
5575 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5577 arc_t arc;
5579 if (start_state->pass_num == curr_state_graph_pass_num)
5580 return;
5581 start_state->pass_num = curr_state_graph_pass_num;
5582 (*applied_func) (start_state);
5583 for (arc = first_out_arc (start_state);
5584 arc != NULL;
5585 arc = next_out_arc (arc))
5586 pass_state_graph (arc->to_state, applied_func);
5589 /* This recursive function passes all states of AUTOMATON and applies
5590 APPLIED_FUNC to them. */
5591 static void
5592 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5594 curr_state_graph_pass_num++;
5595 pass_state_graph (automaton->start_state, applied_func);
5598 /* The function initializes code for passing of all states. */
5599 static void
5600 initiate_pass_states (void)
5602 curr_state_graph_pass_num = 0;
5605 /* The following vla is used for storing pointers to all achieved
5606 states. */
5607 static VEC(state_t,heap) *all_achieved_states;
5609 /* This function is called by function pass_states to add an achieved
5610 STATE. */
5611 static void
5612 add_achieved_state (state_t state)
5614 VEC_safe_push (state_t,heap, all_achieved_states, state);
5617 /* The function sets up equivalence numbers of insns which mark all
5618 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5619 nonzero value) or by equiv_class_num_2 of the destination state.
5620 The function returns number of out arcs of STATE. */
5621 static void
5622 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5624 arc_t arc;
5626 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5628 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5629 arc->insn->insn_reserv_decl->equiv_class_num
5630 = (odd_iteration_flag
5631 ? arc->to_state->equiv_class_num_1
5632 : arc->to_state->equiv_class_num_2);
5633 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5637 /* The function clears equivalence numbers and alt_states in all insns
5638 which mark all out arcs of STATE. */
5639 static void
5640 clear_arc_insns_equiv_num (state_t state)
5642 arc_t arc;
5644 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5645 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5649 /* The following function returns TRUE if STATE reserves the unit with
5650 UNIT_NUM on the first cycle. */
5651 static int
5652 first_cycle_unit_presence (state_t state, int unit_num)
5654 alt_state_t alt_state;
5656 if (state->component_states == NULL)
5657 return test_unit_reserv (state->reservs, 0, unit_num);
5658 else
5660 for (alt_state = state->component_states;
5661 alt_state != NULL;
5662 alt_state = alt_state->next_sorted_alt_state)
5663 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5664 return true;
5666 return false;
5669 /* This fills in the presence_signature[] member of STATE. */
5670 static void
5671 cache_presence (state_t state)
5673 int i, num = 0;
5674 unsigned int sz;
5675 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5676 / (sizeof (int) * CHAR_BIT);
5678 state->presence_signature = create_node (sz * sizeof (int));
5679 for (i = 0; i < description->units_num; i++)
5680 if (units_array [i]->query_p)
5682 int presence1_p = first_cycle_unit_presence (state, i);
5683 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5684 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5685 num++;
5689 /* The function returns nonzero value if STATE is not equivalent to
5690 ANOTHER_STATE from the same current partition on equivalence
5691 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5692 output arcs. Iteration of making equivalence partition is defined
5693 by ODD_ITERATION_FLAG. */
5694 static int
5695 state_is_differed (state_t state, state_t another_state,
5696 int odd_iteration_flag)
5698 arc_t arc;
5699 unsigned int sz, si;
5701 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5703 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5704 / (sizeof (int) * CHAR_BIT);
5706 for (si = 0; si < sz; si++)
5707 gcc_assert (state->presence_signature[si]
5708 == another_state->presence_signature[si]);
5710 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5712 if ((odd_iteration_flag
5713 ? arc->to_state->equiv_class_num_1
5714 : arc->to_state->equiv_class_num_2)
5715 != arc->insn->insn_reserv_decl->equiv_class_num)
5716 return 1;
5719 return 0;
5722 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5723 and return -1, 0 or 1. This function can be used as predicate for
5724 qsort(). It requires the member presence_signature[] of both
5725 states be filled. */
5726 static int
5727 compare_states_for_equiv (const void *state_ptr_1,
5728 const void *state_ptr_2)
5730 state_t s1 = *(state_t *)state_ptr_1;
5731 state_t s2 = *(state_t *)state_ptr_2;
5732 unsigned int sz, si;
5733 if (s1->num_out_arcs < s2->num_out_arcs)
5734 return -1;
5735 else if (s1->num_out_arcs > s2->num_out_arcs)
5736 return 1;
5738 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5739 / (sizeof (int) * CHAR_BIT);
5741 for (si = 0; si < sz; si++)
5742 if (s1->presence_signature[si] < s2->presence_signature[si])
5743 return -1;
5744 else if (s1->presence_signature[si] > s2->presence_signature[si])
5745 return 1;
5746 return 0;
5749 /* The function makes initial partition of STATES on equivalent
5750 classes and saves it into *CLASSES. This function requires the input
5751 to be sorted via compare_states_for_equiv(). */
5752 static int
5753 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5755 size_t i;
5756 state_t prev = 0;
5757 int class_num = 1;
5759 *classes = VEC_alloc (state_t,heap, 150);
5760 for (i = 0; i < VEC_length (state_t, states); i++)
5762 state_t state = VEC_index (state_t, states, i);
5763 if (prev)
5765 if (compare_states_for_equiv (&prev, &state) != 0)
5767 VEC_safe_push (state_t,heap, *classes, prev);
5768 class_num++;
5769 prev = NULL;
5772 state->equiv_class_num_1 = class_num;
5773 state->next_equiv_class_state = prev;
5774 prev = state;
5776 if (prev)
5777 VEC_safe_push (state_t,heap, *classes, prev);
5778 return class_num;
5781 /* The function copies pointers to equivalent states from vla FROM
5782 into vla TO. */
5783 static void
5784 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5786 VEC_free (state_t,heap, *to);
5787 *to = VEC_copy (state_t,heap, from);
5790 /* The function processes equivalence class given by its first state,
5791 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5792 are not equivalent states, the function partitions the class
5793 removing nonequivalent states and placing them in
5794 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5795 assigns it to the state equivalence number. If the class has been
5796 partitioned, the function returns nonzero value. */
5797 static int
5798 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5799 VEC(state_t,heap) **next_iteration_classes,
5800 int *new_equiv_class_num_ptr)
5802 state_t new_equiv_class;
5803 int partition_p;
5804 state_t curr_state;
5805 state_t prev_state;
5806 state_t next_state;
5808 partition_p = 0;
5810 while (first_state != NULL)
5812 new_equiv_class = NULL;
5813 if (first_state->next_equiv_class_state != NULL)
5815 /* There are more one states in the class equivalence. */
5816 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5817 for (prev_state = first_state,
5818 curr_state = first_state->next_equiv_class_state;
5819 curr_state != NULL;
5820 curr_state = next_state)
5822 next_state = curr_state->next_equiv_class_state;
5823 if (state_is_differed (curr_state, first_state,
5824 odd_iteration_flag))
5826 /* Remove curr state from the class equivalence. */
5827 prev_state->next_equiv_class_state = next_state;
5828 /* Add curr state to the new class equivalence. */
5829 curr_state->next_equiv_class_state = new_equiv_class;
5830 if (new_equiv_class == NULL)
5831 (*new_equiv_class_num_ptr)++;
5832 if (odd_iteration_flag)
5833 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5834 else
5835 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5836 new_equiv_class = curr_state;
5837 partition_p = 1;
5839 else
5840 prev_state = curr_state;
5842 clear_arc_insns_equiv_num (first_state);
5844 if (new_equiv_class != NULL)
5845 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5846 first_state = new_equiv_class;
5848 return partition_p;
5851 /* The function finds equivalent states of AUTOMATON. */
5852 static void
5853 evaluate_equiv_classes (automaton_t automaton,
5854 VEC(state_t,heap) **equiv_classes)
5856 int new_equiv_class_num;
5857 int odd_iteration_flag;
5858 int finish_flag;
5859 VEC (state_t,heap) *next_iteration_classes;
5860 size_t i;
5862 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5863 pass_states (automaton, add_achieved_state);
5864 pass_states (automaton, cache_presence);
5865 qsort (VEC_address (state_t, all_achieved_states),
5866 VEC_length (state_t, all_achieved_states),
5867 sizeof (state_t), compare_states_for_equiv);
5869 odd_iteration_flag = 0;
5870 new_equiv_class_num = init_equiv_class (all_achieved_states,
5871 &next_iteration_classes);
5875 odd_iteration_flag = !odd_iteration_flag;
5876 finish_flag = 1;
5877 copy_equiv_class (equiv_classes, next_iteration_classes);
5879 /* Transfer equiv numbers for the next iteration. */
5880 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5881 if (odd_iteration_flag)
5882 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5883 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5884 else
5885 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5886 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5888 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5889 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5890 odd_iteration_flag,
5891 &next_iteration_classes,
5892 &new_equiv_class_num))
5893 finish_flag = 0;
5895 while (!finish_flag);
5896 VEC_free (state_t,heap, next_iteration_classes);
5897 VEC_free (state_t,heap, all_achieved_states);
5900 /* The function merges equivalent states of AUTOMATON. */
5901 static void
5902 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5904 state_t curr_state;
5905 state_t new_state;
5906 state_t first_class_state;
5907 alt_state_t alt_states;
5908 alt_state_t alt_state, new_alt_state;
5909 arc_t curr_arc;
5910 arc_t next_arc;
5911 size_t i;
5913 /* Create states corresponding to equivalence classes containing two
5914 or more states. */
5915 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5917 curr_state = VEC_index (state_t, equiv_classes, i);
5918 if (curr_state->next_equiv_class_state != NULL)
5920 /* There are more one states in the class equivalence. */
5921 /* Create new compound state. */
5922 new_state = get_free_state (0, automaton);
5923 alt_states = NULL;
5924 first_class_state = curr_state;
5925 for (curr_state = first_class_state;
5926 curr_state != NULL;
5927 curr_state = curr_state->next_equiv_class_state)
5929 curr_state->equiv_class_state = new_state;
5930 if (curr_state->component_states == NULL)
5932 new_alt_state = get_free_alt_state ();
5933 new_alt_state->state = curr_state;
5934 new_alt_state->next_alt_state = alt_states;
5935 alt_states = new_alt_state;
5937 else
5938 for (alt_state = curr_state->component_states;
5939 alt_state != NULL;
5940 alt_state = alt_state->next_sorted_alt_state)
5942 new_alt_state = get_free_alt_state ();
5943 new_alt_state->state = alt_state->state;
5944 new_alt_state->next_alt_state = alt_states;
5945 alt_states = new_alt_state;
5948 /* Its is important that alt states were sorted before and
5949 after merging to have the same querying results. */
5950 new_state->component_states = uniq_sort_alt_states (alt_states);
5952 else
5953 curr_state->equiv_class_state = curr_state;
5956 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5958 curr_state = VEC_index (state_t, equiv_classes, i);
5959 if (curr_state->next_equiv_class_state != NULL)
5961 first_class_state = curr_state;
5962 /* Create new arcs output from the state corresponding to
5963 equiv class. */
5964 for (curr_arc = first_out_arc (first_class_state);
5965 curr_arc != NULL;
5966 curr_arc = next_out_arc (curr_arc))
5967 add_arc (first_class_state->equiv_class_state,
5968 curr_arc->to_state->equiv_class_state,
5969 curr_arc->insn);
5970 /* Delete output arcs from states of given class equivalence. */
5971 for (curr_state = first_class_state;
5972 curr_state != NULL;
5973 curr_state = curr_state->next_equiv_class_state)
5975 if (automaton->start_state == curr_state)
5976 automaton->start_state = curr_state->equiv_class_state;
5977 /* Delete the state and its output arcs. */
5978 for (curr_arc = first_out_arc (curr_state);
5979 curr_arc != NULL;
5980 curr_arc = next_arc)
5982 next_arc = next_out_arc (curr_arc);
5983 free_arc (curr_arc);
5987 else
5989 /* Change `to_state' of arcs output from the state of given
5990 equivalence class. */
5991 for (curr_arc = first_out_arc (curr_state);
5992 curr_arc != NULL;
5993 curr_arc = next_out_arc (curr_arc))
5994 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5999 /* The function sets up new_cycle_p for states if there is arc to the
6000 state marked by advance_cycle_insn_decl. */
6001 static void
6002 set_new_cycle_flags (state_t state)
6004 arc_t arc;
6006 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6007 if (arc->insn->insn_reserv_decl
6008 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6009 arc->to_state->new_cycle_p = 1;
6012 /* The top level function for minimization of deterministic
6013 AUTOMATON. */
6014 static void
6015 minimize_DFA (automaton_t automaton)
6017 VEC(state_t,heap) *equiv_classes = 0;
6019 evaluate_equiv_classes (automaton, &equiv_classes);
6020 merge_states (automaton, equiv_classes);
6021 pass_states (automaton, set_new_cycle_flags);
6023 VEC_free (state_t,heap, equiv_classes);
6026 /* Values of two variables are counted number of states and arcs in an
6027 automaton. */
6028 static int curr_counted_states_num;
6029 static int curr_counted_arcs_num;
6031 /* The function is called by function `pass_states' to count states
6032 and arcs of an automaton. */
6033 static void
6034 incr_states_and_arcs_nums (state_t state)
6036 arc_t arc;
6038 curr_counted_states_num++;
6039 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6040 curr_counted_arcs_num++;
6043 /* The function counts states and arcs of AUTOMATON. */
6044 static void
6045 count_states_and_arcs (automaton_t automaton, int *states_num,
6046 int *arcs_num)
6048 curr_counted_states_num = 0;
6049 curr_counted_arcs_num = 0;
6050 pass_states (automaton, incr_states_and_arcs_nums);
6051 *states_num = curr_counted_states_num;
6052 *arcs_num = curr_counted_arcs_num;
6055 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6056 recognition after checking and simplifying IR of the
6057 description. */
6058 static void
6059 build_automaton (automaton_t automaton)
6061 int states_num;
6062 int arcs_num;
6064 ticker_on (&NDFA_time);
6065 if (progress_flag)
6067 if (automaton->corresponding_automaton_decl == NULL)
6068 fprintf (stderr, "Create anonymous automaton");
6069 else
6070 fprintf (stderr, "Create automaton `%s'",
6071 automaton->corresponding_automaton_decl->name);
6072 fprintf (stderr, " (1 dot is 100 new states):");
6074 make_automaton (automaton);
6075 if (progress_flag)
6076 fprintf (stderr, " done\n");
6077 ticker_off (&NDFA_time);
6078 count_states_and_arcs (automaton, &states_num, &arcs_num);
6079 automaton->NDFA_states_num = states_num;
6080 automaton->NDFA_arcs_num = arcs_num;
6081 ticker_on (&NDFA_to_DFA_time);
6082 if (progress_flag)
6084 if (automaton->corresponding_automaton_decl == NULL)
6085 fprintf (stderr, "Make anonymous DFA");
6086 else
6087 fprintf (stderr, "Make DFA `%s'",
6088 automaton->corresponding_automaton_decl->name);
6089 fprintf (stderr, " (1 dot is 100 new states):");
6091 NDFA_to_DFA (automaton);
6092 if (progress_flag)
6093 fprintf (stderr, " done\n");
6094 ticker_off (&NDFA_to_DFA_time);
6095 count_states_and_arcs (automaton, &states_num, &arcs_num);
6096 automaton->DFA_states_num = states_num;
6097 automaton->DFA_arcs_num = arcs_num;
6098 if (!no_minimization_flag)
6100 ticker_on (&minimize_time);
6101 if (progress_flag)
6103 if (automaton->corresponding_automaton_decl == NULL)
6104 fprintf (stderr, "Minimize anonymous DFA...");
6105 else
6106 fprintf (stderr, "Minimize DFA `%s'...",
6107 automaton->corresponding_automaton_decl->name);
6109 minimize_DFA (automaton);
6110 if (progress_flag)
6111 fprintf (stderr, "done\n");
6112 ticker_off (&minimize_time);
6113 count_states_and_arcs (automaton, &states_num, &arcs_num);
6114 automaton->minimal_DFA_states_num = states_num;
6115 automaton->minimal_DFA_arcs_num = arcs_num;
6121 /* The page contains code for enumeration of all states of an automaton. */
6123 /* Variable used for enumeration of all states of an automaton. Its
6124 value is current number of automaton states. */
6125 static int curr_state_order_num;
6127 /* The function is called by function `pass_states' for enumerating
6128 states. */
6129 static void
6130 set_order_state_num (state_t state)
6132 state->order_state_num = curr_state_order_num;
6133 curr_state_order_num++;
6136 /* The function enumerates all states of AUTOMATON. */
6137 static void
6138 enumerate_states (automaton_t automaton)
6140 curr_state_order_num = 0;
6141 pass_states (automaton, set_order_state_num);
6142 automaton->achieved_states_num = curr_state_order_num;
6147 /* The page contains code for finding equivalent automaton insns
6148 (ainsns). */
6150 /* The function inserts AINSN into cyclic list
6151 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6152 static ainsn_t
6153 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6154 ainsn_t cyclic_equiv_class_insn_list)
6156 if (cyclic_equiv_class_insn_list == NULL)
6157 ainsn->next_equiv_class_insn = ainsn;
6158 else
6160 ainsn->next_equiv_class_insn
6161 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6162 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6164 return ainsn;
6167 /* The function deletes equiv_class_insn into cyclic list of
6168 equivalent ainsns. */
6169 static void
6170 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6172 ainsn_t curr_equiv_class_insn;
6173 ainsn_t prev_equiv_class_insn;
6175 prev_equiv_class_insn = equiv_class_insn;
6176 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6177 curr_equiv_class_insn != equiv_class_insn;
6178 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6179 prev_equiv_class_insn = curr_equiv_class_insn;
6180 if (prev_equiv_class_insn != equiv_class_insn)
6181 prev_equiv_class_insn->next_equiv_class_insn
6182 = equiv_class_insn->next_equiv_class_insn;
6185 /* The function processes AINSN of a state in order to find equivalent
6186 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6187 state. */
6188 static void
6189 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6191 ainsn_t next_insn;
6192 ainsn_t curr_insn;
6193 ainsn_t cyclic_insn_list;
6194 arc_t arc;
6196 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6197 curr_insn = ainsn;
6198 /* New class of ainsns which are not equivalent to given ainsn. */
6199 cyclic_insn_list = NULL;
6202 next_insn = curr_insn->next_equiv_class_insn;
6203 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6204 if (arc == NULL
6205 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6206 != arc->to_state))
6208 delete_ainsn_from_equiv_class (curr_insn);
6209 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6210 cyclic_insn_list);
6212 curr_insn = next_insn;
6214 while (curr_insn != ainsn);
6217 /* The function processes STATE in order to find equivalent ainsns. */
6218 static void
6219 process_state_for_insn_equiv_partition (state_t state)
6221 arc_t arc;
6222 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6224 /* Process insns of the arcs. */
6225 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6226 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6227 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6228 process_insn_equiv_class (arc->insn, insn_arcs_array);
6230 free (insn_arcs_array);
6233 /* The function searches for equivalent ainsns of AUTOMATON. */
6234 static void
6235 set_insn_equiv_classes (automaton_t automaton)
6237 ainsn_t ainsn;
6238 ainsn_t first_insn;
6239 ainsn_t curr_insn;
6240 ainsn_t cyclic_insn_list;
6241 ainsn_t insn_with_same_reservs;
6242 int equiv_classes_num;
6244 /* All insns are included in one equivalence class. */
6245 cyclic_insn_list = NULL;
6246 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6247 if (ainsn->first_insn_with_same_reservs)
6248 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6249 cyclic_insn_list);
6250 /* Process insns in order to make equivalence partition. */
6251 pass_states (automaton, process_state_for_insn_equiv_partition);
6252 /* Enumerate equiv classes. */
6253 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6254 /* Set undefined value. */
6255 ainsn->insn_equiv_class_num = -1;
6256 equiv_classes_num = 0;
6257 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6258 if (ainsn->insn_equiv_class_num < 0)
6260 first_insn = ainsn;
6261 gcc_assert (first_insn->first_insn_with_same_reservs);
6262 first_insn->first_ainsn_with_given_equivalence_num = 1;
6263 curr_insn = first_insn;
6266 for (insn_with_same_reservs = curr_insn;
6267 insn_with_same_reservs != NULL;
6268 insn_with_same_reservs
6269 = insn_with_same_reservs->next_same_reservs_insn)
6270 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6271 curr_insn = curr_insn->next_equiv_class_insn;
6273 while (curr_insn != first_insn);
6274 equiv_classes_num++;
6276 automaton->insn_equiv_classes_num = equiv_classes_num;
6281 /* This page contains code for creating DFA(s) and calls functions
6282 building them. */
6285 /* The following value is used to prevent floating point overflow for
6286 estimating an automaton bound. The value should be less DBL_MAX on
6287 the host machine. We use here approximate minimum of maximal
6288 double floating point value required by ANSI C standard. It
6289 will work for non ANSI sun compiler too. */
6291 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6293 /* The function estimate size of the single DFA used by PHR (pipeline
6294 hazards recognizer). */
6295 static double
6296 estimate_one_automaton_bound (void)
6298 decl_t decl;
6299 double one_automaton_estimation_bound;
6300 double root_value;
6301 int i;
6303 one_automaton_estimation_bound = 1.0;
6304 for (i = 0; i < description->decls_num; i++)
6306 decl = description->decls [i];
6307 if (decl->mode == dm_unit)
6309 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6310 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6311 / automata_num);
6312 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6313 > one_automaton_estimation_bound)
6314 one_automaton_estimation_bound *= root_value;
6317 return one_automaton_estimation_bound;
6320 /* The function compares unit declarations according to their maximal
6321 cycle in reservations. */
6322 static int
6323 compare_max_occ_cycle_nums (const void *unit_decl_1,
6324 const void *unit_decl_2)
6326 if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6327 < (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6328 return 1;
6329 else if ((DECL_UNIT (*(decl_t *) unit_decl_1)->max_occ_cycle_num)
6330 == (DECL_UNIT (*(decl_t *) unit_decl_2)->max_occ_cycle_num))
6331 return 0;
6332 else
6333 return -1;
6336 /* The function makes heuristic assigning automata to units. Actually
6337 efficacy of the algorithm has been checked yet??? */
6339 static void
6340 units_to_automata_heuristic_distr (void)
6342 double estimation_bound;
6343 int automaton_num;
6344 int rest_units_num;
6345 double bound_value;
6346 unit_decl_t *unit_decls;
6347 int i, j;
6349 if (description->units_num == 0)
6350 return;
6351 estimation_bound = estimate_one_automaton_bound ();
6352 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6354 for (i = 0, j = 0; i < description->decls_num; i++)
6355 if (description->decls[i]->mode == dm_unit)
6356 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6357 gcc_assert (j == description->units_num);
6359 qsort (unit_decls, description->units_num,
6360 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6362 automaton_num = 0;
6363 bound_value = unit_decls[0]->max_occ_cycle_num;
6364 unit_decls[0]->corresponding_automaton_num = automaton_num;
6366 for (i = 1; i < description->units_num; i++)
6368 rest_units_num = description->units_num - i + 1;
6369 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6370 if (automaton_num < automata_num - 1
6371 && ((automata_num - automaton_num - 1 == rest_units_num)
6372 || (bound_value
6373 > (estimation_bound
6374 / unit_decls[i]->max_occ_cycle_num))))
6376 bound_value = unit_decls[i]->max_occ_cycle_num;
6377 automaton_num++;
6379 else
6380 bound_value *= unit_decls[i]->max_occ_cycle_num;
6381 unit_decls[i]->corresponding_automaton_num = automaton_num;
6383 gcc_assert (automaton_num == automata_num - 1);
6384 free (unit_decls);
6387 /* The functions creates automaton insns for each automata. Automaton
6388 insn is simply insn for given automaton which makes reservation
6389 only of units of the automaton. */
6390 static ainsn_t
6391 create_ainsns (void)
6393 decl_t decl;
6394 ainsn_t first_ainsn;
6395 ainsn_t curr_ainsn;
6396 ainsn_t prev_ainsn;
6397 int i;
6399 first_ainsn = NULL;
6400 prev_ainsn = NULL;
6401 for (i = 0; i < description->decls_num; i++)
6403 decl = description->decls [i];
6404 if (decl->mode == dm_insn_reserv)
6406 curr_ainsn = create_node (sizeof (struct ainsn));
6407 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6408 curr_ainsn->important_p = FALSE;
6409 curr_ainsn->next_ainsn = NULL;
6410 if (prev_ainsn == NULL)
6411 first_ainsn = curr_ainsn;
6412 else
6413 prev_ainsn->next_ainsn = curr_ainsn;
6414 prev_ainsn = curr_ainsn;
6417 return first_ainsn;
6420 /* The function assigns automata to units according to constructions
6421 `define_automaton' in the description. */
6422 static void
6423 units_to_automata_distr (void)
6425 decl_t decl;
6426 int i;
6428 for (i = 0; i < description->decls_num; i++)
6430 decl = description->decls [i];
6431 if (decl->mode == dm_unit)
6433 if (DECL_UNIT (decl)->automaton_decl == NULL
6434 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6435 == NULL))
6436 /* Distribute to the first automaton. */
6437 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6438 else
6439 DECL_UNIT (decl)->corresponding_automaton_num
6440 = (DECL_UNIT (decl)->automaton_decl
6441 ->corresponding_automaton->automaton_order_num);
6446 /* The function creates DFA(s) for fast pipeline hazards recognition
6447 after checking and simplifying IR of the description. */
6448 static void
6449 create_automata (void)
6451 automaton_t curr_automaton;
6452 automaton_t prev_automaton;
6453 decl_t decl;
6454 int curr_automaton_num;
6455 int i;
6457 if (automata_num != 0)
6459 units_to_automata_heuristic_distr ();
6460 for (prev_automaton = NULL, curr_automaton_num = 0;
6461 curr_automaton_num < automata_num;
6462 curr_automaton_num++, prev_automaton = curr_automaton)
6464 curr_automaton = create_node (sizeof (struct automaton));
6465 curr_automaton->ainsn_list = create_ainsns ();
6466 curr_automaton->corresponding_automaton_decl = NULL;
6467 curr_automaton->next_automaton = NULL;
6468 curr_automaton->automaton_order_num = curr_automaton_num;
6469 if (prev_automaton == NULL)
6470 description->first_automaton = curr_automaton;
6471 else
6472 prev_automaton->next_automaton = curr_automaton;
6475 else
6477 curr_automaton_num = 0;
6478 prev_automaton = NULL;
6479 for (i = 0; i < description->decls_num; i++)
6481 decl = description->decls [i];
6482 if (decl->mode == dm_automaton
6483 && DECL_AUTOMATON (decl)->automaton_is_used)
6485 curr_automaton = create_node (sizeof (struct automaton));
6486 curr_automaton->ainsn_list = create_ainsns ();
6487 curr_automaton->corresponding_automaton_decl
6488 = DECL_AUTOMATON (decl);
6489 curr_automaton->next_automaton = NULL;
6490 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6491 curr_automaton->automaton_order_num = curr_automaton_num;
6492 if (prev_automaton == NULL)
6493 description->first_automaton = curr_automaton;
6494 else
6495 prev_automaton->next_automaton = curr_automaton;
6496 curr_automaton_num++;
6497 prev_automaton = curr_automaton;
6500 if (curr_automaton_num == 0)
6502 curr_automaton = create_node (sizeof (struct automaton));
6503 curr_automaton->ainsn_list = create_ainsns ();
6504 curr_automaton->corresponding_automaton_decl = NULL;
6505 curr_automaton->next_automaton = NULL;
6506 description->first_automaton = curr_automaton;
6508 units_to_automata_distr ();
6510 NDFA_time = create_ticker ();
6511 ticker_off (&NDFA_time);
6512 NDFA_to_DFA_time = create_ticker ();
6513 ticker_off (&NDFA_to_DFA_time);
6514 minimize_time = create_ticker ();
6515 ticker_off (&minimize_time);
6516 equiv_time = create_ticker ();
6517 ticker_off (&equiv_time);
6518 for (curr_automaton = description->first_automaton;
6519 curr_automaton != NULL;
6520 curr_automaton = curr_automaton->next_automaton)
6522 if (progress_flag)
6524 if (curr_automaton->corresponding_automaton_decl == NULL)
6525 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6526 else
6527 fprintf (stderr, "Prepare automaton `%s' creation...",
6528 curr_automaton->corresponding_automaton_decl->name);
6530 create_alt_states (curr_automaton);
6531 form_ainsn_with_same_reservs (curr_automaton);
6532 if (progress_flag)
6533 fprintf (stderr, "done\n");
6534 build_automaton (curr_automaton);
6535 enumerate_states (curr_automaton);
6536 ticker_on (&equiv_time);
6537 set_insn_equiv_classes (curr_automaton);
6538 ticker_off (&equiv_time);
6544 /* This page contains code for forming string representation of
6545 regexp. The representation is formed on IR obstack. So you should
6546 not work with IR obstack between regexp_representation and
6547 finish_regexp_representation calls. */
6549 /* This recursive function forms string representation of regexp
6550 (without tailing '\0'). */
6551 static void
6552 form_regexp (regexp_t regexp)
6554 int i;
6556 switch (regexp->mode)
6558 case rm_unit: case rm_reserv:
6560 const char *name = (regexp->mode == rm_unit
6561 ? REGEXP_UNIT (regexp)->name
6562 : REGEXP_RESERV (regexp)->name);
6564 obstack_grow (&irp, name, strlen (name));
6565 break;
6568 case rm_sequence:
6569 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6571 if (i != 0)
6572 obstack_1grow (&irp, ',');
6573 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6575 break;
6577 case rm_allof:
6578 obstack_1grow (&irp, '(');
6579 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6581 if (i != 0)
6582 obstack_1grow (&irp, '+');
6583 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6584 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6585 obstack_1grow (&irp, '(');
6586 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6587 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6588 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6589 obstack_1grow (&irp, ')');
6591 obstack_1grow (&irp, ')');
6592 break;
6594 case rm_oneof:
6595 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6597 if (i != 0)
6598 obstack_1grow (&irp, '|');
6599 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6600 obstack_1grow (&irp, '(');
6601 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6602 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6603 obstack_1grow (&irp, ')');
6605 break;
6607 case rm_repeat:
6609 char digits [30];
6611 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6612 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6613 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6614 obstack_1grow (&irp, '(');
6615 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6616 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6617 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6618 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6619 obstack_1grow (&irp, ')');
6620 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6621 obstack_grow (&irp, digits, strlen (digits));
6622 break;
6625 case rm_nothing:
6626 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6627 break;
6629 default:
6630 gcc_unreachable ();
6634 /* The function returns string representation of REGEXP on IR
6635 obstack. */
6636 static const char *
6637 regexp_representation (regexp_t regexp)
6639 form_regexp (regexp);
6640 obstack_1grow (&irp, '\0');
6641 return obstack_base (&irp);
6644 /* The function frees memory allocated for last formed string
6645 representation of regexp. */
6646 static void
6647 finish_regexp_representation (void)
6649 int length = obstack_object_size (&irp);
6651 obstack_blank_fast (&irp, -length);
6656 /* This page contains code for output PHR (pipeline hazards recognizer). */
6658 /* The function outputs minimal C type which is sufficient for
6659 representation numbers in range min_range_value and
6660 max_range_value. Because host machine and build machine may be
6661 different, we use here minimal values required by ANSI C standard
6662 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6663 approximation. */
6665 static void
6666 output_range_type (FILE *f, long int min_range_value,
6667 long int max_range_value)
6669 if (min_range_value >= 0 && max_range_value <= 255)
6670 fprintf (f, "unsigned char");
6671 else if (min_range_value >= -127 && max_range_value <= 127)
6672 fprintf (f, "signed char");
6673 else if (min_range_value >= 0 && max_range_value <= 65535)
6674 fprintf (f, "unsigned short");
6675 else if (min_range_value >= -32767 && max_range_value <= 32767)
6676 fprintf (f, "short");
6677 else
6678 fprintf (f, "int");
6681 /* The following macro value is used as value of member
6682 `longest_path_length' of state when we are processing path and the
6683 state on the path. */
6685 #define ON_THE_PATH -2
6687 /* The following recursive function searches for the length of the
6688 longest path starting from STATE which does not contain cycles and
6689 `cycle advance' arcs. */
6691 static int
6692 longest_path_length (state_t state)
6694 arc_t arc;
6695 int length, result;
6697 if (state->longest_path_length != UNDEFINED_LONGEST_PATH_LENGTH)
6699 /* We don't expect the path cycle here. Our graph may contain
6700 only cycles with one state on the path not containing `cycle
6701 advance' arcs -- see comment below. */
6702 gcc_assert (state->longest_path_length != ON_THE_PATH);
6704 /* We already visited the state. */
6705 return state->longest_path_length;
6708 result = 0;
6709 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6710 /* Ignore cycles containing one state and `cycle advance' arcs. */
6711 if (arc->to_state != state
6712 && (arc->insn->insn_reserv_decl
6713 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
6715 length = longest_path_length (arc->to_state);
6716 if (length > result)
6717 result = length;
6719 state->longest_path_length = result + 1;
6720 return result;
6723 /* The function outputs all initialization values of VECT. */
6724 static void
6725 output_vect (vla_hwint_t vect)
6727 int els_on_line;
6728 size_t vect_length = VEC_length (vect_el_t, vect);
6729 size_t i;
6731 els_on_line = 1;
6732 if (vect_length == 0)
6733 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6734 else
6735 for (i = 0; i < vect_length; i++)
6737 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6738 if (els_on_line == 10)
6740 els_on_line = 0;
6741 fputs (",\n", output_file);
6743 else if (i < vect_length-1)
6744 fputs (", ", output_file);
6745 els_on_line++;
6749 /* The following is name of the structure which represents DFA(s) for
6750 PHR. */
6751 #define CHIP_NAME "DFA_chip"
6753 /* The following is name of member which represents state of a DFA for
6754 PHR. */
6755 static void
6756 output_chip_member_name (FILE *f, automaton_t automaton)
6758 if (automaton->corresponding_automaton_decl == NULL)
6759 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6760 else
6761 fprintf (f, "%s_automaton_state",
6762 automaton->corresponding_automaton_decl->name);
6765 /* The following is name of temporary variable which stores state of a
6766 DFA for PHR. */
6767 static void
6768 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6770 fprintf (f, "_");
6771 output_chip_member_name (f, automaton);
6774 /* This is name of macro value which is code of pseudo_insn
6775 representing advancing cpu cycle. Its value is used as internal
6776 code unknown insn. */
6777 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6779 /* Output name of translate vector for given automaton. */
6780 static void
6781 output_translate_vect_name (FILE *f, automaton_t automaton)
6783 if (automaton->corresponding_automaton_decl == NULL)
6784 fprintf (f, "translate_%d", automaton->automaton_order_num);
6785 else
6786 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6789 /* Output name for simple transition table representation. */
6790 static void
6791 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6793 if (automaton->corresponding_automaton_decl == NULL)
6794 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6795 else
6796 fprintf (f, "%s_transitions",
6797 automaton->corresponding_automaton_decl->name);
6800 /* Output name of comb vector of the transition table for given
6801 automaton. */
6802 static void
6803 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6805 if (automaton->corresponding_automaton_decl == NULL)
6806 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6807 else
6808 fprintf (f, "%s_transitions",
6809 automaton->corresponding_automaton_decl->name);
6812 /* Output name of check vector of the transition table for given
6813 automaton. */
6814 static void
6815 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6817 if (automaton->corresponding_automaton_decl == NULL)
6818 fprintf (f, "check_%d", automaton->automaton_order_num);
6819 else
6820 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6823 /* Output name of base vector of the transition table for given
6824 automaton. */
6825 static void
6826 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6828 if (automaton->corresponding_automaton_decl == NULL)
6829 fprintf (f, "base_%d", automaton->automaton_order_num);
6830 else
6831 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6834 /* Output name of simple min issue delay table representation. */
6835 static void
6836 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6838 if (automaton->corresponding_automaton_decl == NULL)
6839 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6840 else
6841 fprintf (f, "%s_min_issue_delay",
6842 automaton->corresponding_automaton_decl->name);
6845 /* Output name of deadlock vector for given automaton. */
6846 static void
6847 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6849 if (automaton->corresponding_automaton_decl == NULL)
6850 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6851 else
6852 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6855 /* Output name of reserved units table for AUTOMATON into file F. */
6856 static void
6857 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6859 if (automaton->corresponding_automaton_decl == NULL)
6860 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6861 else
6862 fprintf (f, "%s_reserved_units",
6863 automaton->corresponding_automaton_decl->name);
6866 /* Name of the PHR interface macro. */
6867 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6869 /* Names of an internal functions: */
6870 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6872 /* This is external type of DFA(s) state. */
6873 #define STATE_TYPE_NAME "state_t"
6875 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6877 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6879 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6881 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6883 /* Name of cache of insn dfa codes. */
6884 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6886 /* Name of length of cache of insn dfa codes. */
6887 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6889 /* Names of the PHR interface functions: */
6890 #define SIZE_FUNC_NAME "state_size"
6892 #define TRANSITION_FUNC_NAME "state_transition"
6894 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6896 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6898 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6900 #define RESET_FUNC_NAME "state_reset"
6902 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6904 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6906 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6908 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6910 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6912 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6914 #define DFA_START_FUNC_NAME "dfa_start"
6916 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6918 /* Names of parameters of the PHR interface functions. */
6919 #define STATE_NAME "state"
6921 #define INSN_PARAMETER_NAME "insn"
6923 #define INSN2_PARAMETER_NAME "insn2"
6925 #define CHIP_PARAMETER_NAME "chip"
6927 #define FILE_PARAMETER_NAME "f"
6929 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6931 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6933 /* Names of the variables whose values are internal insn code of rtx
6934 insn. */
6935 #define INTERNAL_INSN_CODE_NAME "insn_code"
6937 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6939 /* Names of temporary variables in some functions. */
6940 #define TEMPORARY_VARIABLE_NAME "temp"
6942 #define I_VARIABLE_NAME "i"
6944 /* Name of result variable in some functions. */
6945 #define RESULT_VARIABLE_NAME "res"
6947 /* Name of function (attribute) to translate insn into internal insn
6948 code. */
6949 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6951 /* Name of function (attribute) to translate insn into internal insn
6952 code with caching. */
6953 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6955 /* Output C type which is used for representation of codes of states
6956 of AUTOMATON. */
6957 static void
6958 output_state_member_type (FILE *f, automaton_t automaton)
6960 output_range_type (f, 0, automaton->achieved_states_num);
6963 /* Output definition of the structure representing current DFA(s)
6964 state(s). */
6965 static void
6966 output_chip_definitions (void)
6968 automaton_t automaton;
6970 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6971 for (automaton = description->first_automaton;
6972 automaton != NULL;
6973 automaton = automaton->next_automaton)
6975 fprintf (output_file, " ");
6976 output_state_member_type (output_file, automaton);
6977 fprintf (output_file, " ");
6978 output_chip_member_name (output_file, automaton);
6979 fprintf (output_file, ";\n");
6981 fprintf (output_file, "};\n\n");
6982 #if 0
6983 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6984 #endif
6988 /* The function outputs translate vector of internal insn code into
6989 insn equivalence class number. The equivalence class number is
6990 used to access to table and vectors representing DFA(s). */
6991 static void
6992 output_translate_vect (automaton_t automaton)
6994 ainsn_t ainsn;
6995 int insn_value;
6996 vla_hwint_t translate_vect;
6998 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
7000 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7001 /* Undefined value */
7002 VEC_quick_push (vect_el_t, translate_vect,
7003 automaton->insn_equiv_classes_num);
7005 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7006 VEC_replace (vect_el_t, translate_vect,
7007 ainsn->insn_reserv_decl->insn_num,
7008 ainsn->insn_equiv_class_num);
7010 fprintf (output_file,
7011 "/* Vector translating external insn codes to internal ones.*/\n");
7012 fprintf (output_file, "static const ");
7013 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7014 fprintf (output_file, " ");
7015 output_translate_vect_name (output_file, automaton);
7016 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7017 output_vect (translate_vect);
7018 fprintf (output_file, "};\n\n");
7019 VEC_free (vect_el_t,heap, translate_vect);
7022 /* The value in a table state x ainsn -> something which represents
7023 undefined value. */
7024 static int undefined_vect_el_value;
7026 /* The following function returns nonzero value if the best
7027 representation of the table is comb vector. */
7028 static int
7029 comb_vect_p (state_ainsn_table_t tab)
7031 return (2 * VEC_length (vect_el_t, tab->full_vect)
7032 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7035 /* The following function creates new table for AUTOMATON. */
7036 static state_ainsn_table_t
7037 create_state_ainsn_table (automaton_t automaton)
7039 state_ainsn_table_t tab;
7040 int full_vect_length;
7041 int i;
7043 tab = create_node (sizeof (struct state_ainsn_table));
7044 tab->automaton = automaton;
7046 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7047 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7049 tab->base_vect = 0;
7050 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7051 automaton->achieved_states_num);
7053 full_vect_length = (automaton->insn_equiv_classes_num
7054 * automaton->achieved_states_num);
7055 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7056 for (i = 0; i < full_vect_length; i++)
7057 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7059 tab->min_base_vect_el_value = 0;
7060 tab->max_base_vect_el_value = 0;
7061 tab->min_comb_vect_el_value = 0;
7062 tab->max_comb_vect_el_value = 0;
7063 return tab;
7066 /* The following function outputs the best C representation of the
7067 table TAB of given TABLE_NAME. */
7068 static void
7069 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7070 void (*output_full_vect_name_func) (FILE *, automaton_t),
7071 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7072 void (*output_check_vect_name_func) (FILE *, automaton_t),
7073 void (*output_base_vect_name_func) (FILE *, automaton_t))
7075 if (!comb_vect_p (tab))
7077 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7078 fprintf (output_file, "static const ");
7079 output_range_type (output_file, tab->min_comb_vect_el_value,
7080 tab->max_comb_vect_el_value);
7081 fprintf (output_file, " ");
7082 (*output_full_vect_name_func) (output_file, tab->automaton);
7083 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7084 output_vect (tab->full_vect);
7085 fprintf (output_file, "};\n\n");
7087 else
7089 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7090 fprintf (output_file, "static const ");
7091 output_range_type (output_file, tab->min_comb_vect_el_value,
7092 tab->max_comb_vect_el_value);
7093 fprintf (output_file, " ");
7094 (*output_comb_vect_name_func) (output_file, tab->automaton);
7095 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7096 output_vect (tab->comb_vect);
7097 fprintf (output_file, "};\n\n");
7098 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7099 fprintf (output_file, "static const ");
7100 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7101 fprintf (output_file, " ");
7102 (*output_check_vect_name_func) (output_file, tab->automaton);
7103 fprintf (output_file, "[] = {\n");
7104 output_vect (tab->check_vect);
7105 fprintf (output_file, "};\n\n");
7106 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7107 fprintf (output_file, "static const ");
7108 output_range_type (output_file, tab->min_base_vect_el_value,
7109 tab->max_base_vect_el_value);
7110 fprintf (output_file, " ");
7111 (*output_base_vect_name_func) (output_file, tab->automaton);
7112 fprintf (output_file, "[] = {\n");
7113 output_vect (tab->base_vect);
7114 fprintf (output_file, "};\n\n");
7118 /* The following function adds vector VECT to table TAB as its line
7119 with number VECT_NUM. */
7120 static void
7121 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7123 int vect_length;
7124 size_t real_vect_length;
7125 int comb_vect_index;
7126 int comb_vect_els_num;
7127 int vect_index;
7128 int first_unempty_vect_index;
7129 int additional_els_num;
7130 int no_state_value;
7131 vect_el_t vect_el;
7132 int i;
7133 unsigned long vect_mask, comb_vect_mask;
7135 vect_length = VEC_length (vect_el_t, vect);
7136 gcc_assert (vect_length);
7137 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7138 real_vect_length = tab->automaton->insn_equiv_classes_num;
7139 /* Form full vector in the table: */
7141 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7142 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7143 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7144 full_base + vect_length);
7145 for (i = 0; i < vect_length; i++)
7146 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7147 VEC_index (vect_el_t, vect, i));
7149 /* Form comb vector in the table: */
7150 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7151 == VEC_length (vect_el_t, tab->check_vect));
7153 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7154 for (first_unempty_vect_index = 0;
7155 first_unempty_vect_index < vect_length;
7156 first_unempty_vect_index++)
7157 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7158 != undefined_vect_el_value)
7159 break;
7161 /* Search for the place in comb vect for the inserted vect. */
7163 /* Slow case. */
7164 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7166 for (comb_vect_index = 0;
7167 comb_vect_index < comb_vect_els_num;
7168 comb_vect_index++)
7170 for (vect_index = first_unempty_vect_index;
7171 vect_index < vect_length
7172 && vect_index + comb_vect_index < comb_vect_els_num;
7173 vect_index++)
7174 if (VEC_index (vect_el_t, vect, vect_index)
7175 != undefined_vect_el_value
7176 && (VEC_index (vect_el_t, tab->comb_vect,
7177 vect_index + comb_vect_index)
7178 != undefined_vect_el_value))
7179 break;
7180 if (vect_index >= vect_length
7181 || vect_index + comb_vect_index >= comb_vect_els_num)
7182 break;
7184 goto found;
7187 /* Fast case. */
7188 vect_mask = 0;
7189 for (vect_index = first_unempty_vect_index;
7190 vect_index < vect_length;
7191 vect_index++)
7193 vect_mask = vect_mask << 1;
7194 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7195 vect_mask |= 1;
7198 /* Search for the place in comb vect for the inserted vect. */
7199 comb_vect_index = 0;
7200 if (comb_vect_els_num == 0)
7201 goto found;
7203 comb_vect_mask = 0;
7204 for (vect_index = first_unempty_vect_index;
7205 vect_index < vect_length && vect_index < comb_vect_els_num;
7206 vect_index++)
7208 comb_vect_mask <<= 1;
7209 if (vect_index + comb_vect_index < comb_vect_els_num
7210 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7211 != undefined_vect_el_value)
7212 comb_vect_mask |= 1;
7214 if ((vect_mask & comb_vect_mask) == 0)
7215 goto found;
7217 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7218 comb_vect_index++, i++)
7220 comb_vect_mask = (comb_vect_mask << 1) | 1;
7221 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7222 == undefined_vect_el_value);
7223 if ((vect_mask & comb_vect_mask) == 0)
7224 goto found;
7226 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7228 comb_vect_mask <<= 1;
7229 if ((vect_mask & comb_vect_mask) == 0)
7230 goto found;
7233 found:
7234 /* Slot was found. */
7235 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7236 if (additional_els_num < 0)
7237 additional_els_num = 0;
7238 /* Expand comb and check vectors. */
7239 vect_el = undefined_vect_el_value;
7240 no_state_value = tab->automaton->achieved_states_num;
7241 while (additional_els_num > 0)
7243 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7244 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7245 additional_els_num--;
7247 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7248 >= comb_vect_index + real_vect_length);
7249 /* Fill comb and check vectors. */
7250 for (vect_index = 0; vect_index < vect_length; vect_index++)
7251 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7253 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7254 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7255 comb_vect_index + vect_index)
7256 == undefined_vect_el_value);
7257 gcc_assert (x >= 0);
7258 if (tab->max_comb_vect_el_value < x)
7259 tab->max_comb_vect_el_value = x;
7260 if (tab->min_comb_vect_el_value > x)
7261 tab->min_comb_vect_el_value = x;
7262 VEC_replace (vect_el_t, tab->comb_vect,
7263 comb_vect_index + vect_index, x);
7264 VEC_replace (vect_el_t, tab->check_vect,
7265 comb_vect_index + vect_index, vect_num);
7267 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7268 tab->max_comb_vect_el_value = undefined_vect_el_value;
7269 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7270 tab->min_comb_vect_el_value = undefined_vect_el_value;
7271 if (tab->max_base_vect_el_value < comb_vect_index)
7272 tab->max_base_vect_el_value = comb_vect_index;
7273 if (tab->min_base_vect_el_value > comb_vect_index)
7274 tab->min_base_vect_el_value = comb_vect_index;
7276 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7279 /* Return number of out arcs of STATE. */
7280 static int
7281 out_state_arcs_num (state_t state)
7283 int result;
7284 arc_t arc;
7286 result = 0;
7287 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7289 gcc_assert (arc->insn);
7290 if (arc->insn->first_ainsn_with_given_equivalence_num)
7291 result++;
7293 return result;
7296 /* Compare number of possible transitions from the states. */
7297 static int
7298 compare_transition_els_num (const void *state_ptr_1,
7299 const void *state_ptr_2)
7301 int transition_els_num_1;
7302 int transition_els_num_2;
7304 transition_els_num_1 = out_state_arcs_num (*(state_t *) state_ptr_1);
7305 transition_els_num_2 = out_state_arcs_num (*(state_t *) state_ptr_2);
7306 if (transition_els_num_1 < transition_els_num_2)
7307 return 1;
7308 else if (transition_els_num_1 == transition_els_num_2)
7309 return 0;
7310 else
7311 return -1;
7314 /* The function adds element EL_VALUE to vector VECT for a table state
7315 x AINSN. */
7316 static void
7317 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7319 int equiv_class_num;
7320 int vect_index;
7322 gcc_assert (ainsn);
7323 equiv_class_num = ainsn->insn_equiv_class_num;
7324 for (vect_index = VEC_length (vect_el_t, *vect);
7325 vect_index <= equiv_class_num;
7326 vect_index++)
7327 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7328 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7331 /* This is for forming vector of states of an automaton. */
7332 static VEC(state_t,heap) *output_states_vect;
7334 /* The function is called by function pass_states. The function adds
7335 STATE to `output_states_vect'. */
7336 static void
7337 add_states_vect_el (state_t state)
7339 VEC_safe_push (state_t,heap, output_states_vect, state);
7342 /* Form and output vectors (comb, check, base or full vector)
7343 representing transition table of AUTOMATON. */
7344 static void
7345 output_trans_table (automaton_t automaton)
7347 size_t i;
7348 arc_t arc;
7349 vla_hwint_t transition_vect = 0;
7351 undefined_vect_el_value = automaton->achieved_states_num;
7352 automaton->trans_table = create_state_ainsn_table (automaton);
7353 /* Create vect of pointers to states ordered by num of transitions
7354 from the state (state with the maximum num is the first). */
7355 output_states_vect = 0;
7356 pass_states (automaton, add_states_vect_el);
7357 qsort (VEC_address (state_t, output_states_vect),
7358 VEC_length (state_t, output_states_vect),
7359 sizeof (state_t), compare_transition_els_num);
7361 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7363 VEC_truncate (vect_el_t, transition_vect, 0);
7364 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7365 arc != NULL;
7366 arc = next_out_arc (arc))
7368 gcc_assert (arc->insn);
7369 if (arc->insn->first_ainsn_with_given_equivalence_num)
7370 add_vect_el (&transition_vect, arc->insn,
7371 arc->to_state->order_state_num);
7373 add_vect (automaton->trans_table,
7374 VEC_index (state_t, output_states_vect, i)->order_state_num,
7375 transition_vect);
7377 output_state_ainsn_table
7378 (automaton->trans_table, "state transitions",
7379 output_trans_full_vect_name, output_trans_comb_vect_name,
7380 output_trans_check_vect_name, output_trans_base_vect_name);
7382 VEC_free (state_t,heap, output_states_vect);
7383 VEC_free (vect_el_t,heap, transition_vect);
7386 /* The current number of passing states to find minimal issue delay
7387 value for an ainsn and state. */
7388 static int curr_state_pass_num;
7390 /* This recursive function passes states to find minimal issue delay
7391 value for AINSN. The state being visited is STATE. The function
7392 returns minimal issue delay value for AINSN in STATE or -1 if we
7393 enter into a loop. */
7394 static int
7395 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7397 arc_t arc;
7398 int min_insn_issue_delay, insn_issue_delay;
7400 if (state->state_pass_num == curr_state_pass_num
7401 || state->min_insn_issue_delay != -1)
7402 /* We've entered into a loop or already have the correct value for
7403 given state and ainsn. */
7404 return state->min_insn_issue_delay;
7405 state->state_pass_num = curr_state_pass_num;
7406 min_insn_issue_delay = -1;
7407 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7408 if (arc->insn == ainsn)
7410 min_insn_issue_delay = 0;
7411 break;
7413 else
7415 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7416 if (insn_issue_delay != -1)
7418 if (arc->insn->insn_reserv_decl
7419 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7420 insn_issue_delay++;
7421 if (min_insn_issue_delay == -1
7422 || min_insn_issue_delay > insn_issue_delay)
7424 min_insn_issue_delay = insn_issue_delay;
7425 if (insn_issue_delay == 0)
7426 break;
7430 return min_insn_issue_delay;
7433 /* The function searches minimal issue delay value for AINSN in STATE.
7434 The function can return negative value if we can not issue AINSN. We
7435 will report about it later. */
7436 static int
7437 min_issue_delay (state_t state, ainsn_t ainsn)
7439 curr_state_pass_num++;
7440 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7441 return state->min_insn_issue_delay;
7444 /* The function initiates code for finding minimal issue delay values.
7445 It should be called only once. */
7446 static void
7447 initiate_min_issue_delay_pass_states (void)
7449 curr_state_pass_num = 0;
7452 /* Form and output vectors representing minimal issue delay table of
7453 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7454 the ainsn. */
7455 static void
7456 output_min_issue_delay_table (automaton_t automaton)
7458 vla_hwint_t min_issue_delay_vect;
7459 vla_hwint_t compressed_min_issue_delay_vect;
7460 vect_el_t min_delay;
7461 ainsn_t ainsn;
7462 size_t i, min_issue_delay_len;
7463 size_t compressed_min_issue_delay_len;
7464 size_t cfactor;
7466 /* Create vect of pointers to states ordered by num of transitions
7467 from the state (state with the maximum num is the first). */
7468 output_states_vect = 0;
7469 pass_states (automaton, add_states_vect_el);
7471 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7472 * automaton->insn_equiv_classes_num);
7473 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7474 for (i = 0; i < min_issue_delay_len; i++)
7475 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7477 automaton->max_min_delay = 0;
7478 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7479 if (ainsn->first_ainsn_with_given_equivalence_num)
7481 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7482 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7483 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7485 state_t s = VEC_index (state_t, output_states_vect, i);
7486 min_delay = min_issue_delay (s, ainsn);
7487 if (automaton->max_min_delay < min_delay)
7488 automaton->max_min_delay = min_delay;
7489 VEC_replace (vect_el_t, min_issue_delay_vect,
7490 s->order_state_num
7491 * automaton->insn_equiv_classes_num
7492 + ainsn->insn_equiv_class_num,
7493 min_delay);
7496 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7497 fprintf (output_file, "static const ");
7498 output_range_type (output_file, 0, automaton->max_min_delay);
7499 fprintf (output_file, " ");
7500 output_min_issue_delay_vect_name (output_file, automaton);
7501 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7502 /* Compress the vector. */
7503 if (automaton->max_min_delay < 2)
7504 cfactor = 8;
7505 else if (automaton->max_min_delay < 4)
7506 cfactor = 4;
7507 else if (automaton->max_min_delay < 16)
7508 cfactor = 2;
7509 else
7510 cfactor = 1;
7511 automaton->min_issue_delay_table_compression_factor = cfactor;
7513 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7514 compressed_min_issue_delay_vect
7515 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7517 for (i = 0; i < compressed_min_issue_delay_len; i++)
7518 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7520 for (i = 0; i < min_issue_delay_len; i++)
7522 size_t ci = i / cfactor;
7523 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7524 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7526 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7527 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7529 output_vect (compressed_min_issue_delay_vect);
7530 fprintf (output_file, "};\n\n");
7531 VEC_free (state_t,heap, output_states_vect);
7532 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7533 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7536 /* Form and output vector representing the locked states of
7537 AUTOMATON. */
7538 static void
7539 output_dead_lock_vect (automaton_t automaton)
7541 size_t i;
7542 arc_t arc;
7543 vla_hwint_t dead_lock_vect = 0;
7545 /* Create vect of pointers to states ordered by num of
7546 transitions from the state (state with the maximum num is the
7547 first). */
7548 automaton->locked_states = 0;
7549 output_states_vect = 0;
7550 pass_states (automaton, add_states_vect_el);
7552 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7553 VEC_length (state_t, output_states_vect));
7554 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7556 state_t s = VEC_index (state_t, output_states_vect, i);
7557 arc = first_out_arc (s);
7558 gcc_assert (arc);
7559 if (next_out_arc (arc) == NULL
7560 && (arc->insn->insn_reserv_decl
7561 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7563 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7564 automaton->locked_states++;
7566 else
7567 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7569 if (automaton->locked_states == 0)
7570 return;
7572 fprintf (output_file, "/* Vector for locked state flags. */\n");
7573 fprintf (output_file, "static const ");
7574 output_range_type (output_file, 0, 1);
7575 fprintf (output_file, " ");
7576 output_dead_lock_vect_name (output_file, automaton);
7577 fprintf (output_file, "[] = {\n");
7578 output_vect (dead_lock_vect);
7579 fprintf (output_file, "};\n\n");
7580 VEC_free (state_t,heap, output_states_vect);
7581 VEC_free (vect_el_t,heap, dead_lock_vect);
7584 /* Form and output vector representing reserved units of the states of
7585 AUTOMATON. */
7586 static void
7587 output_reserved_units_table (automaton_t automaton)
7589 vla_hwint_t reserved_units_table = 0;
7590 int state_byte_size;
7591 int reserved_units_size;
7592 size_t n;
7593 int i;
7595 if (description->query_units_num == 0)
7596 return;
7598 /* Create vect of pointers to states. */
7599 output_states_vect = 0;
7600 pass_states (automaton, add_states_vect_el);
7601 /* Create vector. */
7602 state_byte_size = (description->query_units_num + 7) / 8;
7603 reserved_units_size = (VEC_length (state_t, output_states_vect)
7604 * state_byte_size);
7606 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7608 for (i = 0; i < reserved_units_size; i++)
7609 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7610 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7612 state_t s = VEC_index (state_t, output_states_vect, n);
7613 for (i = 0; i < description->units_num; i++)
7614 if (units_array [i]->query_p
7615 && first_cycle_unit_presence (s, i))
7617 int ri = (s->order_state_num * state_byte_size
7618 + units_array [i]->query_num / 8);
7619 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7621 x += 1 << (units_array [i]->query_num % 8);
7622 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7625 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7626 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7627 fprintf (output_file, "static const ");
7628 output_range_type (output_file, 0, 255);
7629 fprintf (output_file, " ");
7630 output_reserved_units_table_name (output_file, automaton);
7631 fprintf (output_file, "[] = {\n");
7632 output_vect (reserved_units_table);
7633 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7634 CPU_UNITS_QUERY_MACRO_NAME);
7636 VEC_free (state_t,heap, output_states_vect);
7637 VEC_free (vect_el_t,heap, reserved_units_table);
7640 /* The function outputs all tables representing DFA(s) used for fast
7641 pipeline hazards recognition. */
7642 static void
7643 output_tables (void)
7645 automaton_t automaton;
7647 initiate_min_issue_delay_pass_states ();
7648 for (automaton = description->first_automaton;
7649 automaton != NULL;
7650 automaton = automaton->next_automaton)
7652 output_translate_vect (automaton);
7653 output_trans_table (automaton);
7654 output_min_issue_delay_table (automaton);
7655 output_dead_lock_vect (automaton);
7656 output_reserved_units_table (automaton);
7658 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7659 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7662 /* The function outputs definition and value of PHR interface variable
7663 `max_insn_queue_index'. Its value is not less than maximal queue
7664 length needed for the insn scheduler. */
7665 static void
7666 output_max_insn_queue_index_def (void)
7668 int i, max, latency;
7669 decl_t decl;
7671 max = description->max_insn_reserv_cycles;
7672 for (i = 0; i < description->decls_num; i++)
7674 decl = description->decls [i];
7675 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7677 latency = DECL_INSN_RESERV (decl)->default_latency;
7678 if (latency > max)
7679 max = latency;
7681 else if (decl->mode == dm_bypass)
7683 latency = DECL_BYPASS (decl)->latency;
7684 if (latency > max)
7685 max = latency;
7688 for (i = 0; (1 << i) <= max; i++)
7690 gcc_assert (i >= 0);
7691 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7692 (1 << i) - 1);
7695 /* The function outputs switch cases for insn reservations using
7696 function *output_automata_list_code. */
7697 static void
7698 output_insn_code_cases (void (*output_automata_list_code)
7699 (automata_list_el_t))
7701 decl_t decl, decl2;
7702 int i, j;
7704 for (i = 0; i < description->decls_num; i++)
7706 decl = description->decls [i];
7707 if (decl->mode == dm_insn_reserv)
7708 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7710 for (i = 0; i < description->decls_num; i++)
7712 decl = description->decls [i];
7713 if (decl->mode == dm_insn_reserv
7714 && !DECL_INSN_RESERV (decl)->processed_p)
7716 for (j = i; j < description->decls_num; j++)
7718 decl2 = description->decls [j];
7719 if (decl2->mode == dm_insn_reserv
7720 && (DECL_INSN_RESERV (decl2)->important_automata_list
7721 == DECL_INSN_RESERV (decl)->important_automata_list))
7723 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7724 fprintf (output_file, " case %d: /* %s */\n",
7725 DECL_INSN_RESERV (decl2)->insn_num,
7726 DECL_INSN_RESERV (decl2)->name);
7729 (*output_automata_list_code)
7730 (DECL_INSN_RESERV (decl)->important_automata_list);
7736 /* The function outputs a code for evaluation of a minimal delay of
7737 issue of insns which have reservations in given AUTOMATA_LIST. */
7738 static void
7739 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7741 automata_list_el_t el;
7742 automaton_t automaton;
7744 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7746 automaton = el->automaton;
7747 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7748 output_min_issue_delay_vect_name (output_file, automaton);
7749 fprintf (output_file,
7750 (automaton->min_issue_delay_table_compression_factor != 1
7751 ? " [(" : " ["));
7752 output_translate_vect_name (output_file, automaton);
7753 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7754 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7755 output_chip_member_name (output_file, automaton);
7756 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7757 if (automaton->min_issue_delay_table_compression_factor == 1)
7758 fprintf (output_file, "];\n");
7759 else
7761 fprintf (output_file, ") / %d];\n",
7762 automaton->min_issue_delay_table_compression_factor);
7763 fprintf (output_file, " %s = (%s >> (8 - (",
7764 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7765 output_translate_vect_name (output_file, automaton);
7766 fprintf
7767 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7768 INTERNAL_INSN_CODE_NAME,
7769 automaton->min_issue_delay_table_compression_factor,
7770 8 / automaton->min_issue_delay_table_compression_factor,
7771 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7772 - 1);
7774 if (el == automata_list)
7775 fprintf (output_file, " %s = %s;\n",
7776 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7777 else
7779 fprintf (output_file, " if (%s > %s)\n",
7780 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7781 fprintf (output_file, " %s = %s;\n",
7782 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7785 fprintf (output_file, " break;\n\n");
7788 /* Output function `internal_min_issue_delay'. */
7789 static void
7790 output_internal_min_issue_delay_func (void)
7792 fprintf (output_file,
7793 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7794 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7795 CHIP_NAME, CHIP_PARAMETER_NAME);
7796 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7797 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7798 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7799 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7800 fprintf (output_file,
7801 "\n default:\n %s = -1;\n break;\n }\n",
7802 RESULT_VARIABLE_NAME);
7803 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7804 fprintf (output_file, "}\n\n");
7807 /* The function outputs a code changing state after issue of insns
7808 which have reservations in given AUTOMATA_LIST. */
7809 static void
7810 output_automata_list_transition_code (automata_list_el_t automata_list)
7812 automata_list_el_t el, next_el;
7814 fprintf (output_file, " {\n");
7815 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7816 for (el = automata_list;; el = next_el)
7818 next_el = el->next_automata_list_el;
7819 if (next_el == NULL)
7820 break;
7821 fprintf (output_file, " ");
7822 output_state_member_type (output_file, el->automaton);
7823 fprintf (output_file, " ");
7824 output_temp_chip_member_name (output_file, el->automaton);
7825 fprintf (output_file, ";\n");
7827 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7828 if (comb_vect_p (el->automaton->trans_table))
7830 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7831 output_trans_base_vect_name (output_file, el->automaton);
7832 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7833 output_chip_member_name (output_file, el->automaton);
7834 fprintf (output_file, "] + ");
7835 output_translate_vect_name (output_file, el->automaton);
7836 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7837 fprintf (output_file, " if (");
7838 output_trans_check_vect_name (output_file, el->automaton);
7839 fprintf (output_file, " [%s] != %s->",
7840 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7841 output_chip_member_name (output_file, el->automaton);
7842 fprintf (output_file, ")\n");
7843 fprintf (output_file, " return %s (%s, %s);\n",
7844 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7845 CHIP_PARAMETER_NAME);
7846 fprintf (output_file, " else\n");
7847 fprintf (output_file, " ");
7848 if (el->next_automata_list_el != NULL)
7849 output_temp_chip_member_name (output_file, el->automaton);
7850 else
7852 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7853 output_chip_member_name (output_file, el->automaton);
7855 fprintf (output_file, " = ");
7856 output_trans_comb_vect_name (output_file, el->automaton);
7857 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7859 else
7861 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7862 output_trans_full_vect_name (output_file, el->automaton);
7863 fprintf (output_file, " [");
7864 output_translate_vect_name (output_file, el->automaton);
7865 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7866 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7867 output_chip_member_name (output_file, el->automaton);
7868 fprintf (output_file, " * %d];\n",
7869 el->automaton->insn_equiv_classes_num);
7870 fprintf (output_file, " if (%s >= %d)\n",
7871 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7872 fprintf (output_file, " return %s (%s, %s);\n",
7873 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7874 CHIP_PARAMETER_NAME);
7875 fprintf (output_file, " else\n ");
7876 if (el->next_automata_list_el != NULL)
7877 output_temp_chip_member_name (output_file, el->automaton);
7878 else
7880 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7881 output_chip_member_name (output_file, el->automaton);
7883 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7885 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7886 for (el = automata_list;; el = next_el)
7888 next_el = el->next_automata_list_el;
7889 if (next_el == NULL)
7890 break;
7891 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7892 output_chip_member_name (output_file, el->automaton);
7893 fprintf (output_file, " = ");
7894 output_temp_chip_member_name (output_file, el->automaton);
7895 fprintf (output_file, ";\n");
7897 fprintf (output_file, " return -1;\n");
7898 fprintf (output_file, " }\n");
7901 /* Output function `internal_state_transition'. */
7902 static void
7903 output_internal_trans_func (void)
7905 fprintf (output_file,
7906 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7907 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7908 CHIP_NAME, CHIP_PARAMETER_NAME);
7909 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7910 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7911 output_insn_code_cases (output_automata_list_transition_code);
7912 fprintf (output_file, "\n default:\n return -1;\n }\n");
7913 fprintf (output_file, "}\n\n");
7916 /* Output code
7918 if (insn != 0)
7920 insn_code = dfa_insn_code (insn);
7921 if (insn_code > DFA__ADVANCE_CYCLE)
7922 return code;
7924 else
7925 insn_code = DFA__ADVANCE_CYCLE;
7927 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7928 code denotes CODE. */
7929 static void
7930 output_internal_insn_code_evaluation (const char *insn_name,
7931 const char *insn_code_name,
7932 int code)
7934 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7935 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7936 DFA_INSN_CODE_FUNC_NAME, insn_name);
7937 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7938 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7939 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7940 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7944 /* This function outputs `dfa_insn_code' and its helper function
7945 `dfa_insn_code_enlarge'. */
7946 static void
7947 output_dfa_insn_code_func (void)
7949 /* Emacs c-mode gets really confused if there's a { or } in column 0
7950 inside a string, so don't do that. */
7951 fprintf (output_file, "\
7952 static void\n\
7953 dfa_insn_code_enlarge (int uid)\n\
7954 {\n\
7955 int i = %s;\n\
7956 %s = 2 * uid;\n\
7957 %s = xrealloc (%s,\n\
7958 %s * sizeof(int));\n\
7959 for (; i < %s; i++)\n\
7960 %s[i] = -1;\n}\n\n",
7961 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7962 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7963 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7964 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7965 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7966 DFA_INSN_CODES_VARIABLE_NAME);
7967 fprintf (output_file, "\
7968 static inline int\n%s (rtx %s)\n\
7969 {\n\
7970 int uid = INSN_UID (%s);\n\
7971 int %s;\n\n",
7972 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7973 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7975 fprintf (output_file,
7976 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7977 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7978 fprintf (output_file, " %s = %s[uid];\n",
7979 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7980 fprintf (output_file, "\
7981 if (%s < 0)\n\
7982 {\n\
7983 %s = %s (%s);\n\
7984 %s[uid] = %s;\n\
7985 }\n",
7986 INTERNAL_INSN_CODE_NAME,
7987 INTERNAL_INSN_CODE_NAME,
7988 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7989 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7990 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7993 /* The function outputs PHR interface function `state_transition'. */
7994 static void
7995 output_trans_func (void)
7997 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7998 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7999 INSN_PARAMETER_NAME);
8000 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8001 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8002 INTERNAL_INSN_CODE_NAME, -1);
8003 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8004 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, STATE_NAME);
8007 /* Output function `min_issue_delay'. */
8008 static void
8009 output_min_issue_delay_func (void)
8011 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8012 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8013 INSN_PARAMETER_NAME);
8014 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8015 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8016 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8017 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8018 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8019 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8020 fprintf (output_file, " }\n else\n %s = %s;\n",
8021 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8022 fprintf (output_file, "\n return %s (%s, %s);\n",
8023 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8024 STATE_NAME);
8025 fprintf (output_file, "}\n\n");
8028 /* Output function `internal_dead_lock'. */
8029 static void
8030 output_internal_dead_lock_func (void)
8032 automaton_t automaton;
8034 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8035 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8036 fprintf (output_file, "{\n");
8037 for (automaton = description->first_automaton;
8038 automaton != NULL;
8039 automaton = automaton->next_automaton)
8040 if (automaton->locked_states)
8042 fprintf (output_file, " if (");
8043 output_dead_lock_vect_name (output_file, automaton);
8044 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8045 output_chip_member_name (output_file, automaton);
8046 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8048 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8051 /* The function outputs PHR interface function `state_dead_lock_p'. */
8052 static void
8053 output_dead_lock_func (void)
8055 fprintf (output_file, "int\n%s (%s %s)\n",
8056 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8057 fprintf (output_file, "{\n return %s (%s);\n}\n\n",
8058 INTERNAL_DEAD_LOCK_FUNC_NAME, STATE_NAME);
8061 /* Output function `internal_reset'. */
8062 static void
8063 output_internal_reset_func (void)
8065 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8066 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8067 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8068 CHIP_PARAMETER_NAME, CHIP_NAME);
8071 /* The function outputs PHR interface function `state_size'. */
8072 static void
8073 output_size_func (void)
8075 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8076 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8079 /* The function outputs PHR interface function `state_reset'. */
8080 static void
8081 output_reset_func (void)
8083 fprintf (output_file, "void\n%s (%s %s)\n",
8084 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8085 fprintf (output_file, "{\n %s (%s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8086 STATE_NAME);
8089 /* Output function `min_insn_conflict_delay'. */
8090 static void
8091 output_min_insn_conflict_delay_func (void)
8093 fprintf (output_file,
8094 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8095 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8096 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8097 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8098 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8099 INTERNAL_INSN2_CODE_NAME);
8100 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8101 INTERNAL_INSN_CODE_NAME, 0);
8102 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8103 INTERNAL_INSN2_CODE_NAME, 0);
8104 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8105 CHIP_NAME, STATE_NAME, CHIP_NAME);
8106 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8107 fprintf (output_file, " transition = %s (%s, &%s);\n",
8108 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8109 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8110 fprintf (output_file, " return %s (%s, &%s);\n",
8111 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8112 CHIP_NAME);
8113 fprintf (output_file, "}\n\n");
8116 /* Output function `internal_insn_latency'. */
8117 static void
8118 output_internal_insn_latency_func (void)
8120 decl_t decl;
8121 struct bypass_decl *bypass;
8122 int i, j, col;
8123 const char *tabletype = "unsigned char";
8125 /* Find the smallest integer type that can hold all the default
8126 latency values. */
8127 for (i = 0; i < description->decls_num; i++)
8128 if (description->decls[i]->mode == dm_insn_reserv)
8130 decl = description->decls[i];
8131 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8132 && tabletype[0] != 'i') /* Don't shrink it. */
8133 tabletype = "unsigned short";
8134 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8135 tabletype = "int";
8138 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",
8139 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8140 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8141 INSN2_PARAMETER_NAME);
8142 fprintf (output_file, "{\n");
8144 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8146 fputs (" return 0;\n}\n\n", output_file);
8147 return;
8150 fprintf (output_file, " static const %s default_latencies[] =\n {",
8151 tabletype);
8153 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8154 if (description->decls[i]->mode == dm_insn_reserv
8155 && description->decls[i] != advance_cycle_insn_decl)
8157 if ((col = (col+1) % 8) == 0)
8158 fputs ("\n ", output_file);
8159 decl = description->decls[i];
8160 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8161 fprintf (output_file, "% 4d,",
8162 DECL_INSN_RESERV (decl)->default_latency);
8164 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8165 fputs ("\n };\n", output_file);
8167 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8168 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8169 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8171 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8172 for (i = 0; i < description->decls_num; i++)
8173 if (description->decls[i]->mode == dm_insn_reserv
8174 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8176 decl = description->decls [i];
8177 fprintf (output_file,
8178 " case %d:\n switch (%s)\n {\n",
8179 DECL_INSN_RESERV (decl)->insn_num,
8180 INTERNAL_INSN2_CODE_NAME);
8181 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8182 bypass != NULL;
8183 bypass = bypass->next)
8185 gcc_assert (bypass->in_insn_reserv->insn_num
8186 != (DECL_INSN_RESERV
8187 (advance_cycle_insn_decl)->insn_num));
8188 fprintf (output_file, " case %d:\n",
8189 bypass->in_insn_reserv->insn_num);
8190 if (bypass->bypass_guard_name == NULL)
8191 fprintf (output_file, " return %d;\n",
8192 bypass->latency);
8193 else
8195 fprintf (output_file,
8196 " if (%s (%s, %s))\n",
8197 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8198 INSN2_PARAMETER_NAME);
8199 fprintf (output_file,
8200 " return %d;\n break;\n",
8201 bypass->latency);
8204 fputs (" }\n break;\n", output_file);
8207 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8208 INTERNAL_INSN_CODE_NAME);
8211 /* The function outputs PHR interface function `insn_latency'. */
8212 static void
8213 output_insn_latency_func (void)
8215 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8216 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8217 fprintf (output_file, "{\n int %s, %s;\n",
8218 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8219 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8220 INTERNAL_INSN_CODE_NAME, 0);
8221 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8222 INTERNAL_INSN2_CODE_NAME, 0);
8223 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8224 INTERNAL_INSN_LATENCY_FUNC_NAME,
8225 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8226 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8229 /* The function outputs PHR interface function `print_reservation'. */
8230 static void
8231 output_print_reservation_func (void)
8233 decl_t decl;
8234 int i, j;
8236 fprintf (output_file,
8237 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8238 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8239 INSN_PARAMETER_NAME);
8241 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8243 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8244 NOTHING_NAME, FILE_PARAMETER_NAME);
8245 return;
8249 fputs (" static const char *const reservation_names[] =\n {",
8250 output_file);
8252 for (i = 0, j = 0; i < description->decls_num; i++)
8254 decl = description->decls [i];
8255 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8257 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8258 j++;
8260 fprintf (output_file, "\n \"%s\",",
8261 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8262 finish_regexp_representation ();
8265 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8267 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8268 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8270 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8271 INSN_PARAMETER_NAME,
8272 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8273 fprintf (output_file, " else\n\
8274 {\n\
8275 %s = %s (%s);\n\
8276 if (%s > %s)\n\
8277 %s = %s;\n\
8278 }\n",
8279 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8280 INSN_PARAMETER_NAME,
8281 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8282 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8284 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8285 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8288 /* The following function is used to sort unit declaration by their
8289 names. */
8290 static int
8291 units_cmp (const void *unit1, const void *unit2)
8293 const unit_decl_t u1 = *(unit_decl_t *) unit1;
8294 const unit_decl_t u2 = *(unit_decl_t *) unit2;
8296 return strcmp (u1->name, u2->name);
8299 /* The following macro value is name of struct containing unit name
8300 and unit code. */
8301 #define NAME_CODE_STRUCT_NAME "name_code"
8303 /* The following macro value is name of table of struct name_code. */
8304 #define NAME_CODE_TABLE_NAME "name_code_table"
8306 /* The following macro values are member names for struct name_code. */
8307 #define NAME_MEMBER_NAME "name"
8308 #define CODE_MEMBER_NAME "code"
8310 /* The following macro values are local variable names for function
8311 `get_cpu_unit_code'. */
8312 #define CMP_VARIABLE_NAME "cmp"
8313 #define LOW_VARIABLE_NAME "l"
8314 #define MIDDLE_VARIABLE_NAME "m"
8315 #define HIGH_VARIABLE_NAME "h"
8317 /* The following function outputs function to obtain internal cpu unit
8318 code by the cpu unit name. */
8319 static void
8320 output_get_cpu_unit_code_func (void)
8322 int i;
8323 unit_decl_t *units;
8325 fprintf (output_file, "int\n%s (const char *%s)\n",
8326 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8327 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8328 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8329 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8330 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8331 fprintf (output_file, " static struct %s %s [] =\n {\n",
8332 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8333 units = xmalloc (sizeof (unit_decl_t) * description->units_num);
8334 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8335 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8336 for (i = 0; i < description->units_num; i++)
8337 if (units [i]->query_p)
8338 fprintf (output_file, " {\"%s\", %d},\n",
8339 units[i]->name, units[i]->query_num);
8340 fprintf (output_file, " };\n\n");
8341 fprintf (output_file, " /* The following is binary search: */\n");
8342 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8343 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8344 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8345 fprintf (output_file, " while (%s <= %s)\n {\n",
8346 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8347 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8348 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8349 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8350 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8351 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8352 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8353 fprintf (output_file, " %s = %s - 1;\n",
8354 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8355 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8356 fprintf (output_file, " %s = %s + 1;\n",
8357 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8358 fprintf (output_file, " else\n");
8359 fprintf (output_file, " return %s [%s].%s;\n }\n",
8360 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8361 fprintf (output_file, " return -1;\n}\n\n");
8362 free (units);
8365 /* The following function outputs function to check reservation of cpu
8366 unit (its internal code will be passed as the function argument) in
8367 given cpu state. */
8368 static void
8369 output_cpu_unit_reservation_p (void)
8371 automaton_t automaton;
8373 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8374 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8375 STATE_TYPE_NAME, STATE_NAME,
8376 CPU_CODE_PARAMETER_NAME);
8377 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8378 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8379 description->query_units_num);
8380 if (description->query_units_num > 0)
8381 for (automaton = description->first_automaton;
8382 automaton != NULL;
8383 automaton = automaton->next_automaton)
8385 fprintf (output_file, " if ((");
8386 output_reserved_units_table_name (output_file, automaton);
8387 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8388 output_chip_member_name (output_file, automaton);
8389 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8390 (description->query_units_num + 7) / 8,
8391 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8392 fprintf (output_file, " return 1;\n");
8394 fprintf (output_file, " return 0;\n}\n\n");
8397 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8398 and 'dfa_clear_single_insn_cache'. */
8399 static void
8400 output_dfa_clean_insn_cache_func (void)
8402 fprintf (output_file,
8403 "void\n%s (void)\n{\n int %s;\n\n",
8404 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8405 fprintf (output_file,
8406 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8407 I_VARIABLE_NAME, I_VARIABLE_NAME,
8408 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8409 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8411 fprintf (output_file,
8412 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8413 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8414 I_VARIABLE_NAME);
8415 fprintf (output_file,
8416 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8417 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8418 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8419 I_VARIABLE_NAME);
8422 /* The function outputs PHR interface function `dfa_start'. */
8423 static void
8424 output_dfa_start_func (void)
8426 fprintf (output_file,
8427 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8428 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8429 fprintf (output_file, " %s = xmalloc (%s * sizeof (int));\n",
8430 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8431 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8434 /* The function outputs PHR interface function `dfa_finish'. */
8435 static void
8436 output_dfa_finish_func (void)
8438 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8439 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8444 /* The page contains code for output description file (readable
8445 representation of original description and generated DFA(s). */
8447 /* The function outputs string representation of IR reservation. */
8448 static void
8449 output_regexp (regexp_t regexp)
8451 fprintf (output_description_file, "%s", regexp_representation (regexp));
8452 finish_regexp_representation ();
8455 /* Output names of units in LIST separated by comma. */
8456 static void
8457 output_unit_set_el_list (unit_set_el_t list)
8459 unit_set_el_t el;
8461 for (el = list; el != NULL; el = el->next_unit_set_el)
8463 if (el != list)
8464 fprintf (output_description_file, ", ");
8465 fprintf (output_description_file, "%s", el->unit_decl->name);
8469 /* Output patterns in LIST separated by comma. */
8470 static void
8471 output_pattern_set_el_list (pattern_set_el_t list)
8473 pattern_set_el_t el;
8474 int i;
8476 for (el = list; el != NULL; el = el->next_pattern_set_el)
8478 if (el != list)
8479 fprintf (output_description_file, ", ");
8480 for (i = 0; i < el->units_num; i++)
8481 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8482 el->unit_decls [i]->name);
8486 /* The function outputs string representation of IR define_reservation
8487 and define_insn_reservation. */
8488 static void
8489 output_description (void)
8491 decl_t decl;
8492 int i;
8494 for (i = 0; i < description->decls_num; i++)
8496 decl = description->decls [i];
8497 if (decl->mode == dm_unit)
8499 if (DECL_UNIT (decl)->excl_list != NULL)
8501 fprintf (output_description_file, "unit %s exlusion_set: ",
8502 DECL_UNIT (decl)->name);
8503 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8504 fprintf (output_description_file, "\n");
8506 if (DECL_UNIT (decl)->presence_list != NULL)
8508 fprintf (output_description_file, "unit %s presence_set: ",
8509 DECL_UNIT (decl)->name);
8510 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8511 fprintf (output_description_file, "\n");
8513 if (DECL_UNIT (decl)->final_presence_list != NULL)
8515 fprintf (output_description_file, "unit %s final_presence_set: ",
8516 DECL_UNIT (decl)->name);
8517 output_pattern_set_el_list
8518 (DECL_UNIT (decl)->final_presence_list);
8519 fprintf (output_description_file, "\n");
8521 if (DECL_UNIT (decl)->absence_list != NULL)
8523 fprintf (output_description_file, "unit %s absence_set: ",
8524 DECL_UNIT (decl)->name);
8525 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8526 fprintf (output_description_file, "\n");
8528 if (DECL_UNIT (decl)->final_absence_list != NULL)
8530 fprintf (output_description_file, "unit %s final_absence_set: ",
8531 DECL_UNIT (decl)->name);
8532 output_pattern_set_el_list
8533 (DECL_UNIT (decl)->final_absence_list);
8534 fprintf (output_description_file, "\n");
8538 fprintf (output_description_file, "\n");
8539 for (i = 0; i < description->decls_num; i++)
8541 decl = description->decls [i];
8542 if (decl->mode == dm_reserv)
8544 fprintf (output_description_file, "reservation %s: ",
8545 DECL_RESERV (decl)->name);
8546 output_regexp (DECL_RESERV (decl)->regexp);
8547 fprintf (output_description_file, "\n");
8549 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8551 fprintf (output_description_file, "insn reservation %s ",
8552 DECL_INSN_RESERV (decl)->name);
8553 print_rtl (output_description_file,
8554 DECL_INSN_RESERV (decl)->condexp);
8555 fprintf (output_description_file, ": ");
8556 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8557 fprintf (output_description_file, "\n");
8559 else if (decl->mode == dm_bypass)
8560 fprintf (output_description_file, "bypass %d %s %s\n",
8561 DECL_BYPASS (decl)->latency,
8562 DECL_BYPASS (decl)->out_insn_name,
8563 DECL_BYPASS (decl)->in_insn_name);
8565 fprintf (output_description_file, "\n\f\n");
8568 /* The function outputs name of AUTOMATON. */
8569 static void
8570 output_automaton_name (FILE *f, automaton_t automaton)
8572 if (automaton->corresponding_automaton_decl == NULL)
8573 fprintf (f, "#%d", automaton->automaton_order_num);
8574 else
8575 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8578 /* Maximal length of line for pretty printing into description
8579 file. */
8580 #define MAX_LINE_LENGTH 70
8582 /* The function outputs units name belonging to AUTOMATON. */
8583 static void
8584 output_automaton_units (automaton_t automaton)
8586 decl_t decl;
8587 const char *name;
8588 int curr_line_length;
8589 int there_is_an_automaton_unit;
8590 int i;
8592 fprintf (output_description_file, "\n Corresponding units:\n");
8593 fprintf (output_description_file, " ");
8594 curr_line_length = 4;
8595 there_is_an_automaton_unit = 0;
8596 for (i = 0; i < description->decls_num; i++)
8598 decl = description->decls [i];
8599 if (decl->mode == dm_unit
8600 && (DECL_UNIT (decl)->corresponding_automaton_num
8601 == automaton->automaton_order_num))
8603 there_is_an_automaton_unit = 1;
8604 name = DECL_UNIT (decl)->name;
8605 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8607 curr_line_length = strlen (name) + 4;
8608 fprintf (output_description_file, "\n ");
8610 else
8612 curr_line_length += strlen (name) + 1;
8613 fprintf (output_description_file, " ");
8615 fprintf (output_description_file, "%s", name);
8618 if (!there_is_an_automaton_unit)
8619 fprintf (output_description_file, "<None>");
8620 fprintf (output_description_file, "\n\n");
8623 /* The following variable is used for forming array of all possible cpu unit
8624 reservations described by the current DFA state. */
8625 static VEC(reserv_sets_t,heap) *state_reservs;
8627 /* The function forms `state_reservs' for STATE. */
8628 static void
8629 add_state_reservs (state_t state)
8631 alt_state_t curr_alt_state;
8633 if (state->component_states != NULL)
8634 for (curr_alt_state = state->component_states;
8635 curr_alt_state != NULL;
8636 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8637 add_state_reservs (curr_alt_state->state);
8638 else
8639 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8642 /* The function outputs readable representation of all out arcs of
8643 STATE. */
8644 static void
8645 output_state_arcs (state_t state)
8647 arc_t arc;
8648 ainsn_t ainsn;
8649 const char *insn_name;
8650 int curr_line_length;
8652 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8654 ainsn = arc->insn;
8655 gcc_assert (ainsn->first_insn_with_same_reservs);
8656 fprintf (output_description_file, " ");
8657 curr_line_length = 7;
8658 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8661 insn_name = ainsn->insn_reserv_decl->name;
8662 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8664 if (ainsn != arc->insn)
8666 fprintf (output_description_file, ",\n ");
8667 curr_line_length = strlen (insn_name) + 6;
8669 else
8670 curr_line_length += strlen (insn_name);
8672 else
8674 curr_line_length += strlen (insn_name);
8675 if (ainsn != arc->insn)
8677 curr_line_length += 2;
8678 fprintf (output_description_file, ", ");
8681 fprintf (output_description_file, "%s", insn_name);
8682 ainsn = ainsn->next_same_reservs_insn;
8684 while (ainsn != NULL);
8685 fprintf (output_description_file, " %d \n",
8686 arc->to_state->order_state_num);
8688 fprintf (output_description_file, "\n");
8691 /* The following function is used for sorting possible cpu unit
8692 reservation of a DFA state. */
8693 static int
8694 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8696 return reserv_sets_cmp (*(reserv_sets_t *) reservs_ptr_1,
8697 *(reserv_sets_t *) reservs_ptr_2);
8700 /* The following function is used for sorting possible cpu unit
8701 reservation of a DFA state. */
8702 static void
8703 remove_state_duplicate_reservs (void)
8705 size_t i, j;
8707 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8708 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8709 VEC_index (reserv_sets_t, state_reservs, i)))
8711 j++;
8712 VEC_replace (reserv_sets_t, state_reservs, j,
8713 VEC_index (reserv_sets_t, state_reservs, i));
8715 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8718 /* The following function output readable representation of DFA(s)
8719 state used for fast recognition of pipeline hazards. State is
8720 described by possible (current and scheduled) cpu unit
8721 reservations. */
8722 static void
8723 output_state (state_t state)
8725 size_t i;
8727 state_reservs = 0;
8729 fprintf (output_description_file, " State #%d", state->order_state_num);
8730 fprintf (output_description_file,
8731 state->new_cycle_p ? " (new cycle)\n" : "\n");
8732 add_state_reservs (state);
8733 qsort (VEC_address (reserv_sets_t, state_reservs),
8734 VEC_length (reserv_sets_t, state_reservs),
8735 sizeof (reserv_sets_t), state_reservs_cmp);
8736 remove_state_duplicate_reservs ();
8737 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8739 fprintf (output_description_file, " ");
8740 output_reserv_sets (output_description_file,
8741 VEC_index (reserv_sets_t, state_reservs, i));
8742 fprintf (output_description_file, "\n");
8744 fprintf (output_description_file, "\n");
8745 output_state_arcs (state);
8746 VEC_free (reserv_sets_t,heap, state_reservs);
8749 /* The following function output readable representation of
8750 DFAs used for fast recognition of pipeline hazards. */
8751 static void
8752 output_automaton_descriptions (void)
8754 automaton_t automaton;
8756 for (automaton = description->first_automaton;
8757 automaton != NULL;
8758 automaton = automaton->next_automaton)
8760 fprintf (output_description_file, "\nAutomaton ");
8761 output_automaton_name (output_description_file, automaton);
8762 fprintf (output_description_file, "\n");
8763 output_automaton_units (automaton);
8764 pass_states (automaton, output_state);
8770 /* The page contains top level function for generation DFA(s) used for
8771 PHR. */
8773 /* The function outputs statistics about work of different phases of
8774 DFA generator. */
8775 static void
8776 output_statistics (FILE *f)
8778 automaton_t automaton;
8779 int states_num;
8780 #ifndef NDEBUG
8781 int transition_comb_vect_els = 0;
8782 int transition_full_vect_els = 0;
8783 int min_issue_delay_vect_els = 0;
8784 int locked_states = 0;
8785 #endif
8787 for (automaton = description->first_automaton;
8788 automaton != NULL;
8789 automaton = automaton->next_automaton)
8791 fprintf (f, "\nAutomaton ");
8792 output_automaton_name (f, automaton);
8793 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8794 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8795 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8796 automaton->DFA_states_num, automaton->DFA_arcs_num);
8797 states_num = automaton->DFA_states_num;
8798 if (!no_minimization_flag)
8800 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8801 automaton->minimal_DFA_states_num,
8802 automaton->minimal_DFA_arcs_num);
8803 states_num = automaton->minimal_DFA_states_num;
8805 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8806 description->insns_num, automaton->insn_equiv_classes_num);
8807 fprintf (f, " %d locked states\n", automaton->locked_states);
8808 #ifndef NDEBUG
8809 fprintf
8810 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8811 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8812 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8813 (comb_vect_p (automaton->trans_table)
8814 ? "use comb vect" : "use simple vect"));
8815 fprintf
8816 (f, "%5ld min delay table els, compression factor %d\n",
8817 (long) states_num * automaton->insn_equiv_classes_num,
8818 automaton->min_issue_delay_table_compression_factor);
8819 transition_comb_vect_els
8820 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8821 transition_full_vect_els
8822 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8823 min_issue_delay_vect_els
8824 += states_num * automaton->insn_equiv_classes_num;
8825 locked_states
8826 += automaton->locked_states;
8827 #endif
8829 #ifndef NDEBUG
8830 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8831 allocated_states_num, allocated_arcs_num);
8832 fprintf (f, "%5d all allocated alternative states\n",
8833 allocated_alt_states_num);
8834 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8835 transition_comb_vect_els, transition_full_vect_els);
8836 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8837 fprintf (f, "%5d all locked states\n", locked_states);
8838 #endif
8841 /* The function output times of work of different phases of DFA
8842 generator. */
8843 static void
8844 output_time_statistics (FILE *f)
8846 fprintf (f, "\n transformation: ");
8847 print_active_time (f, transform_time);
8848 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8849 print_active_time (f, NDFA_time);
8850 if (ndfa_flag)
8852 fprintf (f, ", NDFA -> DFA: ");
8853 print_active_time (f, NDFA_to_DFA_time);
8855 fprintf (f, "\n DFA minimization: ");
8856 print_active_time (f, minimize_time);
8857 fprintf (f, ", making insn equivalence: ");
8858 print_active_time (f, equiv_time);
8859 fprintf (f, "\n all automaton generation: ");
8860 print_active_time (f, automaton_generation_time);
8861 fprintf (f, ", output: ");
8862 print_active_time (f, output_time);
8863 fprintf (f, "\n");
8866 /* The function generates DFA (deterministic finite state automaton)
8867 for fast recognition of pipeline hazards. No errors during
8868 checking must be fixed before this function call. */
8869 static void
8870 generate (void)
8872 automata_num = split_argument;
8873 if (description->units_num < automata_num)
8874 automata_num = description->units_num;
8875 initiate_states ();
8876 initiate_arcs ();
8877 initiate_automata_lists ();
8878 initiate_pass_states ();
8879 initiate_excl_sets ();
8880 initiate_presence_absence_pattern_sets ();
8881 automaton_generation_time = create_ticker ();
8882 create_automata ();
8883 ticker_off (&automaton_generation_time);
8888 /* This page mainly contains top level functions of pipeline hazards
8889 description translator. */
8891 /* The following macro value is suffix of name of description file of
8892 pipeline hazards description translator. */
8893 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8895 /* The function returns suffix of given file name. The returned
8896 string can not be changed. */
8897 static const char *
8898 file_name_suffix (const char *file_name)
8900 const char *last_period;
8902 for (last_period = NULL; *file_name != '\0'; file_name++)
8903 if (*file_name == '.')
8904 last_period = file_name;
8905 return (last_period == NULL ? file_name : last_period);
8908 /* The function returns base name of given file name, i.e. pointer to
8909 first char after last `/' (or `\' for WIN32) in given file name,
8910 given file name itself if the directory name is absent. The
8911 returned string can not be changed. */
8912 static const char *
8913 base_file_name (const char *file_name)
8915 int directory_name_length;
8917 directory_name_length = strlen (file_name);
8918 #ifdef WIN32
8919 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8920 && file_name[directory_name_length] != '\\')
8921 #else
8922 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8923 #endif
8924 directory_name_length--;
8925 return file_name + directory_name_length + 1;
8928 /* The following is top level function to initialize the work of
8929 pipeline hazards description translator. */
8930 static void
8931 initiate_automaton_gen (int argc, char **argv)
8933 const char *base_name;
8934 int i;
8936 ndfa_flag = 0;
8937 split_argument = 0; /* default value */
8938 no_minimization_flag = 0;
8939 time_flag = 0;
8940 v_flag = 0;
8941 w_flag = 0;
8942 progress_flag = 0;
8943 for (i = 2; i < argc; i++)
8944 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
8945 no_minimization_flag = 1;
8946 else if (strcmp (argv [i], TIME_OPTION) == 0)
8947 time_flag = 1;
8948 else if (strcmp (argv [i], V_OPTION) == 0)
8949 v_flag = 1;
8950 else if (strcmp (argv [i], W_OPTION) == 0)
8951 w_flag = 1;
8952 else if (strcmp (argv [i], NDFA_OPTION) == 0)
8953 ndfa_flag = 1;
8954 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
8955 progress_flag = 1;
8956 else if (strcmp (argv [i], "-split") == 0)
8958 if (i + 1 >= argc)
8959 fatal ("-split has no argument.");
8960 fatal ("option `-split' has not been implemented yet\n");
8961 /* split_argument = atoi (argument_vect [i + 1]); */
8964 /* Initialize IR storage. */
8965 obstack_init (&irp);
8966 initiate_automaton_decl_table ();
8967 initiate_insn_decl_table ();
8968 initiate_decl_table ();
8969 output_file = stdout;
8970 output_description_file = NULL;
8971 base_name = base_file_name (argv[1]);
8972 obstack_grow (&irp, base_name,
8973 strlen (base_name) - strlen (file_name_suffix (base_name)));
8974 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
8975 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
8976 obstack_1grow (&irp, '\0');
8977 output_description_file_name = obstack_base (&irp);
8978 obstack_finish (&irp);
8981 /* The following function checks existence at least one arc marked by
8982 each insn. */
8983 static void
8984 check_automata_insn_issues (void)
8986 automaton_t automaton;
8987 ainsn_t ainsn, reserv_ainsn;
8989 for (automaton = description->first_automaton;
8990 automaton != NULL;
8991 automaton = automaton->next_automaton)
8993 for (ainsn = automaton->ainsn_list;
8994 ainsn != NULL;
8995 ainsn = ainsn->next_ainsn)
8996 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
8998 for (reserv_ainsn = ainsn;
8999 reserv_ainsn != NULL;
9000 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9001 if (automaton->corresponding_automaton_decl != NULL)
9003 if (!w_flag)
9004 error ("Automaton `%s': Insn `%s' will never be issued",
9005 automaton->corresponding_automaton_decl->name,
9006 reserv_ainsn->insn_reserv_decl->name);
9007 else
9008 warning
9009 (0, "Automaton `%s': Insn `%s' will never be issued",
9010 automaton->corresponding_automaton_decl->name,
9011 reserv_ainsn->insn_reserv_decl->name);
9013 else
9015 if (!w_flag)
9016 error ("Insn `%s' will never be issued",
9017 reserv_ainsn->insn_reserv_decl->name);
9018 else
9019 warning (0, "Insn `%s' will never be issued",
9020 reserv_ainsn->insn_reserv_decl->name);
9026 /* The following vla is used for storing pointers to all achieved
9027 states. */
9028 static VEC(state_t,heap) *automaton_states;
9030 /* This function is called by function pass_states to add an achieved
9031 STATE. */
9032 static void
9033 add_automaton_state (state_t state)
9035 VEC_safe_push (state_t,heap, automaton_states, state);
9038 /* The following function forms list of important automata (whose
9039 states may be changed after the insn issue) for each insn. */
9040 static void
9041 form_important_insn_automata_lists (void)
9043 automaton_t automaton;
9044 decl_t decl;
9045 ainsn_t ainsn;
9046 arc_t arc;
9047 int i;
9048 size_t n;
9050 automaton_states = 0;
9051 /* Mark important ainsns. */
9052 for (automaton = description->first_automaton;
9053 automaton != NULL;
9054 automaton = automaton->next_automaton)
9056 VEC_truncate (state_t, automaton_states, 0);
9057 pass_states (automaton, add_automaton_state);
9058 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9060 state_t s = VEC_index (state_t, automaton_states, n);
9061 for (arc = first_out_arc (s);
9062 arc != NULL;
9063 arc = next_out_arc (arc))
9064 if (arc->to_state != s)
9066 gcc_assert (arc->insn->first_insn_with_same_reservs);
9067 for (ainsn = arc->insn;
9068 ainsn != NULL;
9069 ainsn = ainsn->next_same_reservs_insn)
9070 ainsn->important_p = TRUE;
9074 VEC_free (state_t,heap, automaton_states);
9076 /* Create automata sets for the insns. */
9077 for (i = 0; i < description->decls_num; i++)
9079 decl = description->decls [i];
9080 if (decl->mode == dm_insn_reserv)
9082 automata_list_start ();
9083 for (automaton = description->first_automaton;
9084 automaton != NULL;
9085 automaton = automaton->next_automaton)
9086 for (ainsn = automaton->ainsn_list;
9087 ainsn != NULL;
9088 ainsn = ainsn->next_ainsn)
9089 if (ainsn->important_p
9090 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9092 automata_list_add (automaton);
9093 break;
9095 DECL_INSN_RESERV (decl)->important_automata_list
9096 = automata_list_finish ();
9102 /* The following is top level function to generate automat(a,on) for
9103 fast recognition of pipeline hazards. */
9104 static void
9105 expand_automata (void)
9107 int i;
9109 description = create_node (sizeof (struct description)
9110 /* One entry for cycle advancing insn. */
9111 + sizeof (decl_t) * VEC_length (decl_t, decls));
9112 description->decls_num = VEC_length (decl_t, decls);
9113 description->query_units_num = 0;
9114 for (i = 0; i < description->decls_num; i++)
9116 description->decls [i] = VEC_index (decl_t, decls, i);
9117 if (description->decls [i]->mode == dm_unit
9118 && DECL_UNIT (description->decls [i])->query_p)
9119 DECL_UNIT (description->decls [i])->query_num
9120 = description->query_units_num++;
9122 all_time = create_ticker ();
9123 check_time = create_ticker ();
9124 if (progress_flag)
9125 fprintf (stderr, "Check description...");
9126 check_all_description ();
9127 if (progress_flag)
9128 fprintf (stderr, "done\n");
9129 ticker_off (&check_time);
9130 generation_time = create_ticker ();
9131 if (!have_error)
9133 transform_insn_regexps ();
9134 check_unit_distributions_to_automata ();
9136 if (!have_error)
9138 generate ();
9139 check_automata_insn_issues ();
9141 if (!have_error)
9143 form_important_insn_automata_lists ();
9145 ticker_off (&generation_time);
9148 /* The following is top level function to output PHR and to finish
9149 work with pipeline description translator. */
9150 static void
9151 write_automata (void)
9153 output_time = create_ticker ();
9154 if (progress_flag)
9155 fprintf (stderr, "Forming and outputting automata tables...");
9156 output_tables ();
9157 if (progress_flag)
9159 fprintf (stderr, "done\n");
9160 fprintf (stderr, "Output functions to work with automata...");
9162 output_chip_definitions ();
9163 output_max_insn_queue_index_def ();
9164 output_internal_min_issue_delay_func ();
9165 output_internal_trans_func ();
9166 /* Cache of insn dfa codes: */
9167 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9168 fprintf (output_file, "\nstatic int %s;\n\n",
9169 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9170 output_dfa_insn_code_func ();
9171 output_trans_func ();
9172 output_min_issue_delay_func ();
9173 output_internal_dead_lock_func ();
9174 output_dead_lock_func ();
9175 output_size_func ();
9176 output_internal_reset_func ();
9177 output_reset_func ();
9178 output_min_insn_conflict_delay_func ();
9179 output_internal_insn_latency_func ();
9180 output_insn_latency_func ();
9181 output_print_reservation_func ();
9182 /* Output function get_cpu_unit_code. */
9183 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9184 output_get_cpu_unit_code_func ();
9185 output_cpu_unit_reservation_p ();
9186 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9187 CPU_UNITS_QUERY_MACRO_NAME);
9188 output_dfa_clean_insn_cache_func ();
9189 output_dfa_start_func ();
9190 output_dfa_finish_func ();
9191 if (progress_flag)
9192 fprintf (stderr, "done\n");
9193 if (v_flag)
9195 output_description_file = fopen (output_description_file_name, "w");
9196 if (output_description_file == NULL)
9198 perror (output_description_file_name);
9199 exit (FATAL_EXIT_CODE);
9201 if (progress_flag)
9202 fprintf (stderr, "Output automata description...");
9203 output_description ();
9204 output_automaton_descriptions ();
9205 if (progress_flag)
9206 fprintf (stderr, "done\n");
9207 output_statistics (output_description_file);
9209 output_statistics (stderr);
9210 ticker_off (&output_time);
9211 output_time_statistics (stderr);
9212 finish_states ();
9213 finish_arcs ();
9214 finish_automata_lists ();
9215 if (time_flag)
9217 fprintf (stderr, "Summary:\n");
9218 fprintf (stderr, " check time ");
9219 print_active_time (stderr, check_time);
9220 fprintf (stderr, ", generation time ");
9221 print_active_time (stderr, generation_time);
9222 fprintf (stderr, ", all time ");
9223 print_active_time (stderr, all_time);
9224 fprintf (stderr, "\n");
9226 /* Finish all work. */
9227 if (output_description_file != NULL)
9229 fflush (output_description_file);
9230 if (ferror (stdout) != 0)
9231 fatal ("Error in writing DFA description file %s",
9232 output_description_file_name);
9233 fclose (output_description_file);
9235 finish_automaton_decl_table ();
9236 finish_insn_decl_table ();
9237 finish_decl_table ();
9238 obstack_free (&irp, NULL);
9239 if (have_error && output_description_file != NULL)
9240 remove (output_description_file_name);
9244 main (int argc, char **argv)
9246 rtx desc;
9248 progname = "genautomata";
9250 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9251 return (FATAL_EXIT_CODE);
9253 initiate_automaton_gen (argc, argv);
9254 while (1)
9256 int lineno;
9257 int insn_code_number;
9259 desc = read_md_rtx (&lineno, &insn_code_number);
9260 if (desc == NULL)
9261 break;
9263 switch (GET_CODE (desc))
9265 case DEFINE_CPU_UNIT:
9266 gen_cpu_unit (desc);
9267 break;
9269 case DEFINE_QUERY_CPU_UNIT:
9270 gen_query_cpu_unit (desc);
9271 break;
9273 case DEFINE_BYPASS:
9274 gen_bypass (desc);
9275 break;
9277 case EXCLUSION_SET:
9278 gen_excl_set (desc);
9279 break;
9281 case PRESENCE_SET:
9282 gen_presence_set (desc);
9283 break;
9285 case FINAL_PRESENCE_SET:
9286 gen_final_presence_set (desc);
9287 break;
9289 case ABSENCE_SET:
9290 gen_absence_set (desc);
9291 break;
9293 case FINAL_ABSENCE_SET:
9294 gen_final_absence_set (desc);
9295 break;
9297 case DEFINE_AUTOMATON:
9298 gen_automaton (desc);
9299 break;
9301 case AUTOMATA_OPTION:
9302 gen_automata_option (desc);
9303 break;
9305 case DEFINE_RESERVATION:
9306 gen_reserv (desc);
9307 break;
9309 case DEFINE_INSN_RESERVATION:
9310 gen_insn_reserv (desc);
9311 break;
9313 default:
9314 break;
9318 if (have_error)
9319 return FATAL_EXIT_CODE;
9321 puts ("/* Generated automatically by the program `genautomata'\n"
9322 " from the machine description file `md'. */\n\n"
9323 "#include \"config.h\"\n"
9324 "#include \"system.h\"\n"
9325 "#include \"coretypes.h\"\n"
9326 "#include \"tm.h\"\n"
9327 "#include \"rtl.h\"\n"
9328 "#include \"tm_p.h\"\n"
9329 "#include \"insn-config.h\"\n"
9330 "#include \"recog.h\"\n"
9331 "#include \"regs.h\"\n"
9332 "#include \"real.h\"\n"
9333 "#include \"output.h\"\n"
9334 "#include \"insn-attr.h\"\n"
9335 "#include \"toplev.h\"\n"
9336 "#include \"flags.h\"\n"
9337 "#include \"function.h\"\n");
9339 if (VEC_length (decl_t, decls) > 0)
9341 expand_automata ();
9342 write_automata ();
9345 fflush (stdout);
9346 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);