2015-06-11 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / genautomata.c
blob68933fe0eba20c790820a17a116f3e9d0152415d
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000-2015 Free Software Foundation, Inc.
4 Written by Vladimir Makarov <vmakarov@redhat.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3, or (at your option) any
11 later version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* References:
24 1. The finite state automaton based pipeline hazard recognizer and
25 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
26 summit, 2003.
28 2. Detecting pipeline structural hazards quickly. T. Proebsting,
29 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
30 Principles of Programming Languages, pages 280--286, 1994.
32 This article is a good start point to understand usage of finite
33 state automata for pipeline hazard recognizers. But I'd
34 recommend the 1st and 3rd article for more deep understanding.
36 3. Efficient Instruction Scheduling Using Finite State Automata:
37 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
38 article about usage of finite state automata for pipeline hazard
39 recognizers.
41 The current implementation is described in the 1st article and it
42 is different from the 3rd article in the following:
44 1. New operator `|' (alternative) is permitted in functional unit
45 reservation which can be treated deterministically and
46 non-deterministically.
48 2. Possibility of usage of nondeterministic automata too.
50 3. Possibility to query functional unit reservations for given
51 automaton state.
53 4. Several constructions to describe impossible reservations
54 (`exclusion_set', `presence_set', `final_presence_set',
55 `absence_set', and `final_absence_set').
57 5. No reverse automata are generated. Trace instruction scheduling
58 requires this. It can be easily added in the future if we
59 really need this.
61 6. Union of automaton states are not generated yet. It is planned
62 to be implemented. Such feature is needed to make more accurate
63 interlock insn scheduling to get state describing functional
64 unit reservation in a joint CFG point. */
66 /* This file code processes constructions of machine description file
67 which describes automaton used for recognition of processor pipeline
68 hazards by insn scheduler and can be used for other tasks (such as
69 VLIW insn packing.
71 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
72 `gen_bypass', `gen_excl_set', `gen_presence_set',
73 `gen_final_presence_set', `gen_absence_set',
74 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
75 `gen_reserv', `gen_insn_reserv' are called from file
76 `genattrtab.c'. They transform RTL constructions describing
77 automata in .md file into internal representation convenient for
78 further processing.
80 The translator major function `expand_automata' processes the
81 description internal representation into finite state automaton.
82 It can be divided on:
84 o checking correctness of the automaton pipeline description
85 (major function is `check_all_description').
87 o generating automaton (automata) from the description (major
88 function is `make_automaton').
90 o optional transformation of nondeterministic finite state
91 automata into deterministic ones if the alternative operator
92 `|' is treated nondeterministically in the description (major
93 function is NDFA_to_DFA).
95 o optional minimization of the finite state automata by merging
96 equivalent automaton states (major function is `minimize_DFA').
98 o forming tables (some as comb vectors) and attributes
99 representing the automata (functions output_..._table).
101 Function `write_automata' outputs the created finite state
102 automaton as different tables and functions which works with the
103 automata to inquire automaton state and to change its state. These
104 function are used by gcc instruction scheduler and may be some
105 other gcc code. */
107 #include "bconfig.h"
108 #include "system.h"
109 #include "coretypes.h"
110 #include "tm.h"
111 #include "rtl.h"
112 #include "obstack.h"
113 #include "errors.h"
114 #include "gensupport.h"
116 #include <math.h>
117 #include "fnmatch.h"
119 #ifndef CHAR_BIT
120 #define CHAR_BIT 8
121 #endif
123 /* Positions in machine description file. Now they are not used. But
124 they could be used in the future for better diagnostic messages. */
125 typedef int pos_t;
127 /* The following is element of vector of current (and planned in the
128 future) functional unit reservations. */
129 typedef unsigned HOST_WIDE_INT set_el_t;
131 /* Reservations of function units are represented by value of the following
132 type. */
133 typedef set_el_t *reserv_sets_t;
134 typedef const set_el_t *const_reserv_sets_t;
136 /* The following structure describes a ticker. */
137 struct ticker
139 /* The following member value is time of the ticker creation with
140 taking into account time when the ticker is off. Active time of
141 the ticker is current time minus the value. */
142 int modified_creation_time;
143 /* The following member value is time (incremented by one) when the
144 ticker was off. Zero value means that now the ticker is on. */
145 int incremented_off_time;
148 /* The ticker is represented by the following type. */
149 typedef struct ticker ticker_t;
151 /* The following type describes elements of output vectors. */
152 typedef HOST_WIDE_INT vect_el_t;
154 /* Forward declaration of structures of internal representation of
155 pipeline description based on NDFA. */
157 struct unit_decl;
158 struct bypass_decl;
159 struct result_decl;
160 struct automaton_decl;
161 struct unit_pattern_rel_decl;
162 struct reserv_decl;
163 struct insn_reserv_decl;
164 struct decl;
165 struct unit_regexp;
166 struct result_regexp;
167 struct reserv_regexp;
168 struct nothing_regexp;
169 struct sequence_regexp;
170 struct repeat_regexp;
171 struct allof_regexp;
172 struct oneof_regexp;
173 struct regexp;
174 struct description;
175 struct unit_set_el;
176 struct pattern_set_el;
177 struct pattern_reserv;
178 struct state;
179 struct alt_state;
180 struct arc;
181 struct ainsn;
182 struct automaton;
183 struct state_ainsn_table;
185 /* The following typedefs are for brevity. */
186 typedef struct unit_decl *unit_decl_t;
187 typedef const struct unit_decl *const_unit_decl_t;
188 typedef struct decl *decl_t;
189 typedef const struct decl *const_decl_t;
190 typedef struct regexp *regexp_t;
191 typedef struct unit_set_el *unit_set_el_t;
192 typedef struct pattern_set_el *pattern_set_el_t;
193 typedef struct pattern_reserv *pattern_reserv_t;
194 typedef struct alt_state *alt_state_t;
195 typedef struct state *state_t;
196 typedef const struct state *const_state_t;
197 typedef struct arc *arc_t;
198 typedef struct ainsn *ainsn_t;
199 typedef struct automaton *automaton_t;
200 typedef struct automata_list_el *automata_list_el_t;
201 typedef const struct automata_list_el *const_automata_list_el_t;
202 typedef struct state_ainsn_table *state_ainsn_table_t;
204 /* Undefined position. */
205 static pos_t no_pos = 0;
207 /* All IR is stored in the following obstack. */
208 static struct obstack irp;
211 /* Declare vector types for various data structures: */
214 typedef vec<vect_el_t> vla_hwint_t;
216 /* Forward declarations of functions used before their definitions, only. */
217 static regexp_t gen_regexp_sequence (const char *);
218 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
219 reserv_sets_t);
220 static reserv_sets_t get_excl_set (reserv_sets_t);
221 static int check_presence_pattern_sets (reserv_sets_t,
222 reserv_sets_t, int);
223 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
224 int);
225 static arc_t first_out_arc (const_state_t);
226 static arc_t next_out_arc (arc_t);
230 /* Options with the following names can be set up in automata_option
231 construction. Because the strings occur more one time we use the
232 macros. */
234 #define NO_MINIMIZATION_OPTION "-no-minimization"
235 #define TIME_OPTION "-time"
236 #define STATS_OPTION "-stats"
237 #define V_OPTION "-v"
238 #define W_OPTION "-w"
239 #define NDFA_OPTION "-ndfa"
240 #define COLLAPSE_OPTION "-collapse-ndfa"
241 #define NO_COMB_OPTION "-no-comb-vect"
242 #define PROGRESS_OPTION "-progress"
244 /* The following flags are set up by function `initiate_automaton_gen'. */
246 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
247 static int ndfa_flag;
249 /* When making an NDFA, produce additional transitions that collapse
250 NDFA state into a deterministic one suitable for querying CPU units.
251 Provide avance-state transitions only for deterministic states. */
252 static int collapse_flag;
254 /* Do not make minimization of DFA (`-no-minimization'). */
255 static int no_minimization_flag;
257 /* Do not try to generate a comb vector (`-no-comb-vect'). */
258 static int no_comb_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 automata statistics (`-stats'). */
271 static int stats_flag;
273 /* Flag of creation of description file which contains description of
274 result automaton and statistics information (`-v'). */
275 static int v_flag;
277 /* Flag of output of a progress bar showing how many states were
278 generated so far for automaton being processed (`-progress'). */
279 static int progress_flag;
281 /* Flag of generating warning instead of error for non-critical errors
282 (`-w'). */
283 static int w_flag;
286 /* Output file for pipeline hazard recognizer (PHR) being generated.
287 The value is NULL if the file is not defined. */
288 static FILE *output_file;
290 /* Description file of PHR. The value is NULL if the file is not
291 created. */
292 static FILE *output_description_file;
294 /* PHR description file name. */
295 static char *output_description_file_name;
297 /* Value of the following variable is node representing description
298 being processed. This is start point of IR. */
299 static struct description *description;
303 /* This page contains description of IR structure (nodes). */
305 enum decl_mode
307 dm_unit,
308 dm_bypass,
309 dm_automaton,
310 dm_excl,
311 dm_presence,
312 dm_absence,
313 dm_reserv,
314 dm_insn_reserv
317 /* This describes define_cpu_unit and define_query_cpu_unit (see file
318 rtl.def). */
319 struct unit_decl
321 const char *name;
322 /* NULL if the automaton name is absent. */
323 const char *automaton_name;
324 /* If the following value is not zero, the cpu unit reservation is
325 described in define_query_cpu_unit. */
326 char query_p;
328 /* The following fields are defined by checker. */
330 /* The following field value is nonzero if the unit is used in an
331 regexp. */
332 char unit_is_used;
334 /* The following field value is order number (0, 1, ...) of given
335 unit. */
336 int unit_num;
337 /* The following field value is corresponding declaration of
338 automaton which was given in description. If the field value is
339 NULL then automaton in the unit declaration was absent. */
340 struct automaton_decl *automaton_decl;
341 /* The following field value is maximal cycle number (1, ...) on
342 which given unit occurs in insns. Zero value means that given
343 unit is not used in insns. */
344 int max_occ_cycle_num;
345 /* The following field value is minimal cycle number (0, ...) on
346 which given unit occurs in insns. -1 value means that given
347 unit is not used in insns. */
348 int min_occ_cycle_num;
349 /* The following list contains units which conflict with given
350 unit. */
351 unit_set_el_t excl_list;
352 /* The following list contains patterns which are required to
353 reservation of given unit. */
354 pattern_set_el_t presence_list;
355 pattern_set_el_t final_presence_list;
356 /* The following list contains patterns which should be not present
357 in reservation for given unit. */
358 pattern_set_el_t absence_list;
359 pattern_set_el_t final_absence_list;
360 /* The following is used only when `query_p' has nonzero value.
361 This is query number for the unit. */
362 int query_num;
363 /* The following is the last cycle on which the unit was checked for
364 correct distributions of units to automata in a regexp. */
365 int last_distribution_check_cycle;
367 /* The following fields are defined by automaton generator. */
369 /* The following field value is number of the automaton to which
370 given unit belongs. */
371 int corresponding_automaton_num;
372 /* If the following value is not zero, the cpu unit is present in a
373 `exclusion_set' or in right part of a `presence_set',
374 `final_presence_set', `absence_set', and
375 `final_absence_set'define_query_cpu_unit. */
376 char in_set_p;
379 /* This describes define_bypass (see file rtl.def). */
380 struct bypass_decl
382 int latency;
383 const char *out_pattern;
384 const char *in_pattern;
385 const char *bypass_guard_name;
387 /* The following fields are defined by checker. */
389 /* output and input insns of given bypass. */
390 struct insn_reserv_decl *out_insn_reserv;
391 struct insn_reserv_decl *in_insn_reserv;
392 /* The next bypass for given output insn. */
393 struct bypass_decl *next;
396 /* This describes define_automaton (see file rtl.def). */
397 struct automaton_decl
399 const char *name;
401 /* The following fields are defined by automaton generator. */
403 /* The following field value is nonzero if the automaton is used in
404 an regexp definition. */
405 char automaton_is_used;
407 /* The following fields are defined by checker. */
409 /* The following field value is the corresponding automaton. This
410 field is not NULL only if the automaton is present in unit
411 declarations and the automatic partition on automata is not
412 used. */
413 automaton_t corresponding_automaton;
416 /* This describes exclusion relations: exclusion_set (see file
417 rtl.def). */
418 struct excl_rel_decl
420 int all_names_num;
421 int first_list_length;
422 char *names [1];
425 /* This describes unit relations: [final_]presence_set or
426 [final_]absence_set (see file rtl.def). */
427 struct unit_pattern_rel_decl
429 int final_p;
430 int names_num;
431 int patterns_num;
432 char **names;
433 char ***patterns;
436 /* This describes define_reservation (see file rtl.def). */
437 struct reserv_decl
439 const char *name;
440 regexp_t regexp;
442 /* The following fields are defined by checker. */
444 /* The following field value is nonzero if the unit is used in an
445 regexp. */
446 char reserv_is_used;
447 /* The following field is used to check up cycle in expression
448 definition. */
449 int loop_pass_num;
452 /* This describes define_insn_reservation (see file rtl.def). */
453 struct insn_reserv_decl
455 rtx condexp;
456 int default_latency;
457 regexp_t regexp;
458 const char *name;
460 /* The following fields are defined by checker. */
462 /* The following field value is order number (0, 1, ...) of given
463 insn. */
464 int insn_num;
465 /* The following field value is list of bypasses in which given insn
466 is output insn. Bypasses with the same input insn stay one after
467 another in the list in the same order as their occurrences in the
468 description but the bypass without a guard stays always the last
469 in a row of bypasses with the same input insn. */
470 struct bypass_decl *bypass_list;
472 /* The following fields are defined by automaton generator. */
474 /* The following field is the insn regexp transformed that
475 the regexp has not optional regexp, repetition regexp, and an
476 reservation name (i.e. reservation identifiers are changed by the
477 corresponding regexp) and all alternations are the top level
478 of the regexp. The value can be NULL only if it is special
479 insn `cycle advancing'. */
480 regexp_t transformed_regexp;
481 /* The following field value is list of arcs marked given
482 insn. The field is used in transformation NDFA -> DFA. */
483 arc_t arcs_marked_by_insn;
484 /* The two following fields are used during minimization of a finite state
485 automaton. */
486 /* The field value is number of equivalence class of state into
487 which arc marked by given insn enters from a state (fixed during
488 an automaton minimization). */
489 int equiv_class_num;
490 /* The following member value is the list to automata which can be
491 changed by the insn issue. */
492 automata_list_el_t important_automata_list;
493 /* The following member is used to process insn once for output. */
494 int processed_p;
497 /* This contains a declaration mentioned above. */
498 struct decl
500 /* What node in the union? */
501 enum decl_mode mode;
502 pos_t pos;
503 union
505 struct unit_decl unit;
506 struct bypass_decl bypass;
507 struct automaton_decl automaton;
508 struct excl_rel_decl excl;
509 struct unit_pattern_rel_decl presence;
510 struct unit_pattern_rel_decl absence;
511 struct reserv_decl reserv;
512 struct insn_reserv_decl insn_reserv;
513 } decl;
516 /* The following structures represent parsed reservation strings. */
517 enum regexp_mode
519 rm_unit,
520 rm_reserv,
521 rm_nothing,
522 rm_sequence,
523 rm_repeat,
524 rm_allof,
525 rm_oneof
528 /* Cpu unit in reservation. */
529 struct unit_regexp
531 const char *name;
532 unit_decl_t unit_decl;
535 /* Define_reservation in a reservation. */
536 struct reserv_regexp
538 const char *name;
539 struct reserv_decl *reserv_decl;
542 /* Absence of reservation (represented by string `nothing'). */
543 struct nothing_regexp
545 /* This used to be empty but ISO C doesn't allow that. */
546 char unused;
549 /* Representation of reservations separated by ',' (see file
550 rtl.def). */
551 struct sequence_regexp
553 int regexps_num;
554 regexp_t regexps [1];
557 /* Representation of construction `repeat' (see file rtl.def). */
558 struct repeat_regexp
560 int repeat_num;
561 regexp_t regexp;
564 /* Representation of reservations separated by '+' (see file
565 rtl.def). */
566 struct allof_regexp
568 int regexps_num;
569 regexp_t regexps [1];
572 /* Representation of reservations separated by '|' (see file
573 rtl.def). */
574 struct oneof_regexp
576 int regexps_num;
577 regexp_t regexps [1];
580 /* Representation of a reservation string. */
581 struct regexp
583 /* What node in the union? */
584 enum regexp_mode mode;
585 pos_t pos;
586 union
588 struct unit_regexp unit;
589 struct reserv_regexp reserv;
590 struct nothing_regexp nothing;
591 struct sequence_regexp sequence;
592 struct repeat_regexp repeat;
593 struct allof_regexp allof;
594 struct oneof_regexp oneof;
595 } regexp;
598 /* Represents description of pipeline hazard description based on
599 NDFA. */
600 struct description
602 int decls_num, normal_decls_num;
604 /* The following fields are defined by checker. */
606 /* The following fields values are correspondingly number of all
607 units, query units, and insns in the description. */
608 int units_num;
609 int query_units_num;
610 int insns_num;
611 /* The following field value is max length (in cycles) of
612 reservations of insns. The field value is defined only for
613 correct programs. */
614 int max_insn_reserv_cycles;
616 /* The following fields are defined by automaton generator. */
618 /* The following field value is the first automaton. */
619 automaton_t first_automaton;
621 /* The following field is created by pipeline hazard parser and
622 contains all declarations. We allocate additional entries for
623 two special insns which are added by the automaton generator. */
624 decl_t decls [1];
628 /* The following nodes are created in automaton checker. */
630 /* The following nodes represent exclusion set for cpu units. Each
631 element is accessed through only one excl_list. */
632 struct unit_set_el
634 unit_decl_t unit_decl;
635 unit_set_el_t next_unit_set_el;
638 /* The following nodes represent presence or absence pattern for cpu
639 units. Each element is accessed through only one presence_list or
640 absence_list. */
641 struct pattern_set_el
643 /* The number of units in unit_decls. */
644 int units_num;
645 /* The units forming the pattern. */
646 struct unit_decl **unit_decls;
647 pattern_set_el_t next_pattern_set_el;
651 /* The following nodes are created in automaton generator. */
654 /* The following nodes represent presence or absence pattern for cpu
655 units. Each element is accessed through only one element of
656 unit_presence_set_table or unit_absence_set_table. */
657 struct pattern_reserv
659 reserv_sets_t reserv;
660 pattern_reserv_t next_pattern_reserv;
663 /* The following node type describes state automaton. The state may
664 be deterministic or non-deterministic. Non-deterministic state has
665 several component states which represent alternative cpu units
666 reservations. The state also is used for describing a
667 deterministic reservation of automaton insn. */
668 struct state
670 /* The following member value is nonzero if there is a transition by
671 cycle advancing. */
672 int new_cycle_p;
673 /* The following field is list of processor unit reservations on
674 each cycle. */
675 reserv_sets_t reservs;
676 /* The following field is unique number of given state between other
677 states. */
678 int unique_num;
679 /* The following field value is automaton to which given state
680 belongs. */
681 automaton_t automaton;
682 /* The following field value is the first arc output from given
683 state. */
684 arc_t first_out_arc;
685 unsigned int num_out_arcs;
686 /* The following field is used to form NDFA. */
687 char it_was_placed_in_stack_for_NDFA_forming;
688 /* The following field is used to form DFA. */
689 char it_was_placed_in_stack_for_DFA_forming;
690 /* The following field is used to transform NDFA to DFA and DFA
691 minimization. The field value is not NULL if the state is a
692 compound state. In this case the value of field `unit_sets_list'
693 is NULL. All states in the list are in the hash table. The list
694 is formed through field `next_sorted_alt_state'. We should
695 support only one level of nesting state. */
696 alt_state_t component_states;
697 /* The following field is used for passing graph of states. */
698 int pass_num;
699 /* The list of states belonging to one equivalence class is formed
700 with the aid of the following field. */
701 state_t next_equiv_class_state;
702 /* The two following fields are used during minimization of a finite
703 state automaton. */
704 int equiv_class_num_1, equiv_class_num_2;
705 /* The following field is used during minimization of a finite state
706 automaton. The field value is state corresponding to equivalence
707 class to which given state belongs. */
708 state_t equiv_class_state;
709 unsigned int *presence_signature;
710 /* The following field value is the order number of given state.
711 The states in final DFA is enumerated with the aid of the
712 following field. */
713 int order_state_num;
714 /* This member is used for passing states for searching minimal
715 delay time. */
716 int state_pass_num;
717 /* The following member is used to evaluate min issue delay of insn
718 for a state. */
719 int min_insn_issue_delay;
722 /* Automaton arc. */
723 struct arc
725 /* The following field refers for the state into which given arc
726 enters. */
727 state_t to_state;
728 /* The following field describes that the insn issue (with cycle
729 advancing for special insn `cycle advancing' and without cycle
730 advancing for others) makes transition from given state to
731 another given state. */
732 ainsn_t insn;
733 /* The following field value is the next arc output from the same
734 state. */
735 arc_t next_out_arc;
736 /* List of arcs marked given insn is formed with the following
737 field. The field is used in transformation NDFA -> DFA. */
738 arc_t next_arc_marked_by_insn;
741 /* The following node type describes a deterministic alternative in
742 non-deterministic state which characterizes cpu unit reservations
743 of automaton insn or which is part of NDFA. */
744 struct alt_state
746 /* The following field is a deterministic state which characterizes
747 unit reservations of the instruction. */
748 state_t state;
749 /* The following field refers to the next state which characterizes
750 unit reservations of the instruction. */
751 alt_state_t next_alt_state;
752 /* The following field refers to the next state in sorted list. */
753 alt_state_t next_sorted_alt_state;
756 /* The following node type describes insn of automaton. They are
757 labels of FA arcs. */
758 struct ainsn
760 /* The following field value is the corresponding insn declaration
761 of description. */
762 struct insn_reserv_decl *insn_reserv_decl;
763 /* The following field value is the next insn declaration for an
764 automaton. */
765 ainsn_t next_ainsn;
766 /* The following field is states which characterize automaton unit
767 reservations of the instruction. The value can be NULL only if it
768 is special insn `cycle advancing'. */
769 alt_state_t alt_states;
770 /* The following field is sorted list of states which characterize
771 automaton unit reservations of the instruction. The value can be
772 NULL only if it is special insn `cycle advancing'. */
773 alt_state_t sorted_alt_states;
774 /* The following field refers the next automaton insn with
775 the same reservations. */
776 ainsn_t next_same_reservs_insn;
777 /* The following field is flag of the first automaton insn with the
778 same reservations in the declaration list. Only arcs marked such
779 insn is present in the automaton. This significantly decreases
780 memory requirements especially when several automata are
781 formed. */
782 char first_insn_with_same_reservs;
783 /* The following member has nonzero value if there is arc from state of
784 the automaton marked by the ainsn. */
785 char arc_exists_p;
786 /* Cyclic list of insns of an equivalence class is formed with the
787 aid of the following field. */
788 ainsn_t next_equiv_class_insn;
789 /* The following field value is nonzero if the insn declaration is
790 the first insn declaration with given equivalence number. */
791 char first_ainsn_with_given_equivalence_num;
792 /* The following field is number of class of equivalence of insns.
793 It is necessary because many insns may be equivalent with the
794 point of view of pipeline hazards. */
795 int insn_equiv_class_num;
796 /* The following member value is TRUE if there is an arc in the
797 automaton marked by the insn into another state. In other
798 words, the insn can change the state of the automaton. */
799 int important_p;
802 /* The following describes an automaton for PHR. */
803 struct automaton
805 /* The following field value is the list of insn declarations for
806 given automaton. */
807 ainsn_t ainsn_list;
808 /* Pointers to the ainsns corresponding to the special reservations. */
809 ainsn_t advance_ainsn, collapse_ainsn;
811 /* The following field value is the corresponding automaton
812 declaration. This field is not NULL only if the automatic
813 partition on automata is not used. */
814 struct automaton_decl *corresponding_automaton_decl;
815 /* The following field value is the next automaton. */
816 automaton_t next_automaton;
817 /* The following field is start state of FA. There are not unit
818 reservations in the state. */
819 state_t start_state;
820 /* The following field value is number of equivalence classes of
821 insns (see field `insn_equiv_class_num' in
822 `insn_reserv_decl'). */
823 int insn_equiv_classes_num;
824 /* The following field value is number of states of final DFA. */
825 int achieved_states_num;
826 /* The following field value is the order number (0, 1, ...) of
827 given automaton. */
828 int automaton_order_num;
829 /* The following fields contain statistics information about
830 building automaton. */
831 int NDFA_states_num, DFA_states_num;
832 /* The following field value is defined only if minimization of DFA
833 is used. */
834 int minimal_DFA_states_num;
835 int NDFA_arcs_num, DFA_arcs_num;
836 /* The following field value is defined only if minimization of DFA
837 is used. */
838 int minimal_DFA_arcs_num;
839 /* The following member refers for two table state x ainsn -> int.
840 ??? Above sentence is incomprehensible. */
841 state_ainsn_table_t trans_table;
842 /* The following member value is maximal value of min issue delay
843 for insns of the automaton. */
844 int max_min_delay;
845 /* Usually min issue delay is small and we can place several (2, 4,
846 8) elements in one vector element. So the compression factor can
847 be 1 (no compression), 2, 4, 8. */
848 int min_issue_delay_table_compression_factor;
849 /* Total number of locked states in this automaton. */
850 int locked_states;
853 /* The following is the element of the list of automata. */
854 struct automata_list_el
856 /* The automaton itself. */
857 automaton_t automaton;
858 /* The next automata set element. */
859 automata_list_el_t next_automata_list_el;
862 /* The following structure describes a table state X ainsn -> int(>= 0). */
863 struct state_ainsn_table
865 /* Automaton to which given table belongs. */
866 automaton_t automaton;
867 /* The following tree vectors for comb vector implementation of the
868 table. */
869 vla_hwint_t comb_vect;
870 vla_hwint_t check_vect;
871 vla_hwint_t base_vect;
872 /* This is simple implementation of the table. */
873 vla_hwint_t full_vect;
874 /* Minimal and maximal values of the previous vectors. */
875 int min_comb_vect_el_value, max_comb_vect_el_value;
876 int min_base_vect_el_value, max_base_vect_el_value;
879 /* Macros to access members of unions. Use only them for access to
880 union members of declarations and regexps. */
882 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
884 #define DECL_UNIT(d) __extension__ \
885 (({ __typeof (d) const _decl = (d); \
886 if (_decl->mode != dm_unit) \
887 decl_mode_check_failed (_decl->mode, "dm_unit", \
888 __FILE__, __LINE__, __FUNCTION__); \
889 &(_decl)->decl.unit; }))
891 #define DECL_BYPASS(d) __extension__ \
892 (({ __typeof (d) const _decl = (d); \
893 if (_decl->mode != dm_bypass) \
894 decl_mode_check_failed (_decl->mode, "dm_bypass", \
895 __FILE__, __LINE__, __FUNCTION__); \
896 &(_decl)->decl.bypass; }))
898 #define DECL_AUTOMATON(d) __extension__ \
899 (({ __typeof (d) const _decl = (d); \
900 if (_decl->mode != dm_automaton) \
901 decl_mode_check_failed (_decl->mode, "dm_automaton", \
902 __FILE__, __LINE__, __FUNCTION__); \
903 &(_decl)->decl.automaton; }))
905 #define DECL_EXCL(d) __extension__ \
906 (({ __typeof (d) const _decl = (d); \
907 if (_decl->mode != dm_excl) \
908 decl_mode_check_failed (_decl->mode, "dm_excl", \
909 __FILE__, __LINE__, __FUNCTION__); \
910 &(_decl)->decl.excl; }))
912 #define DECL_PRESENCE(d) __extension__ \
913 (({ __typeof (d) const _decl = (d); \
914 if (_decl->mode != dm_presence) \
915 decl_mode_check_failed (_decl->mode, "dm_presence", \
916 __FILE__, __LINE__, __FUNCTION__); \
917 &(_decl)->decl.presence; }))
919 #define DECL_ABSENCE(d) __extension__ \
920 (({ __typeof (d) const _decl = (d); \
921 if (_decl->mode != dm_absence) \
922 decl_mode_check_failed (_decl->mode, "dm_absence", \
923 __FILE__, __LINE__, __FUNCTION__); \
924 &(_decl)->decl.absence; }))
926 #define DECL_RESERV(d) __extension__ \
927 (({ __typeof (d) const _decl = (d); \
928 if (_decl->mode != dm_reserv) \
929 decl_mode_check_failed (_decl->mode, "dm_reserv", \
930 __FILE__, __LINE__, __FUNCTION__); \
931 &(_decl)->decl.reserv; }))
933 #define DECL_INSN_RESERV(d) __extension__ \
934 (({ __typeof (d) const _decl = (d); \
935 if (_decl->mode != dm_insn_reserv) \
936 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
937 __FILE__, __LINE__, __FUNCTION__); \
938 &(_decl)->decl.insn_reserv; }))
940 static const char *decl_name (enum decl_mode);
941 static void decl_mode_check_failed (enum decl_mode, const char *,
942 const char *, int, const char *)
943 ATTRIBUTE_NORETURN;
945 /* Return string representation of declaration mode MODE. */
946 static const char *
947 decl_name (enum decl_mode mode)
949 static char str [100];
951 if (mode == dm_unit)
952 return "dm_unit";
953 else if (mode == dm_bypass)
954 return "dm_bypass";
955 else if (mode == dm_automaton)
956 return "dm_automaton";
957 else if (mode == dm_excl)
958 return "dm_excl";
959 else if (mode == dm_presence)
960 return "dm_presence";
961 else if (mode == dm_absence)
962 return "dm_absence";
963 else if (mode == dm_reserv)
964 return "dm_reserv";
965 else if (mode == dm_insn_reserv)
966 return "dm_insn_reserv";
967 else
968 sprintf (str, "unknown (%d)", (int) mode);
969 return str;
972 /* The function prints message about unexpected declaration and finish
973 the program. */
974 static void
975 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
976 const char *file, int line, const char *func)
978 fprintf
979 (stderr,
980 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
981 file, line, func, expected_mode_str, decl_name (mode));
982 exit (1);
986 #define REGEXP_UNIT(r) __extension__ \
987 (({ struct regexp *const _regexp = (r); \
988 if (_regexp->mode != rm_unit) \
989 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
990 __FILE__, __LINE__, __FUNCTION__); \
991 &(_regexp)->regexp.unit; }))
993 #define REGEXP_RESERV(r) __extension__ \
994 (({ struct regexp *const _regexp = (r); \
995 if (_regexp->mode != rm_reserv) \
996 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
997 __FILE__, __LINE__, __FUNCTION__); \
998 &(_regexp)->regexp.reserv; }))
1000 #define REGEXP_SEQUENCE(r) __extension__ \
1001 (({ struct regexp *const _regexp = (r); \
1002 if (_regexp->mode != rm_sequence) \
1003 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1004 __FILE__, __LINE__, __FUNCTION__); \
1005 &(_regexp)->regexp.sequence; }))
1007 #define REGEXP_REPEAT(r) __extension__ \
1008 (({ struct regexp *const _regexp = (r); \
1009 if (_regexp->mode != rm_repeat) \
1010 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1011 __FILE__, __LINE__, __FUNCTION__); \
1012 &(_regexp)->regexp.repeat; }))
1014 #define REGEXP_ALLOF(r) __extension__ \
1015 (({ struct regexp *const _regexp = (r); \
1016 if (_regexp->mode != rm_allof) \
1017 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1018 __FILE__, __LINE__, __FUNCTION__); \
1019 &(_regexp)->regexp.allof; }))
1021 #define REGEXP_ONEOF(r) __extension__ \
1022 (({ struct regexp *const _regexp = (r); \
1023 if (_regexp->mode != rm_oneof) \
1024 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1025 __FILE__, __LINE__, __FUNCTION__); \
1026 &(_regexp)->regexp.oneof; }))
1028 static const char *regexp_name (enum regexp_mode);
1029 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1030 const char *, int,
1031 const char *) ATTRIBUTE_NORETURN;
1034 /* Return string representation of regexp mode MODE. */
1035 static const char *
1036 regexp_name (enum regexp_mode mode)
1038 switch (mode)
1040 case rm_unit:
1041 return "rm_unit";
1042 case rm_reserv:
1043 return "rm_reserv";
1044 case rm_nothing:
1045 return "rm_nothing";
1046 case rm_sequence:
1047 return "rm_sequence";
1048 case rm_repeat:
1049 return "rm_repeat";
1050 case rm_allof:
1051 return "rm_allof";
1052 case rm_oneof:
1053 return "rm_oneof";
1054 default:
1055 gcc_unreachable ();
1059 /* The function prints message about unexpected regexp and finish the
1060 program. */
1061 static void
1062 regexp_mode_check_failed (enum regexp_mode mode,
1063 const char *expected_mode_str,
1064 const char *file, int line, const char *func)
1066 fprintf
1067 (stderr,
1068 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1069 file, line, func, expected_mode_str, regexp_name (mode));
1070 exit (1);
1073 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1075 #define DECL_UNIT(d) (&(d)->decl.unit)
1076 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1077 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1078 #define DECL_EXCL(d) (&(d)->decl.excl)
1079 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1080 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1081 #define DECL_RESERV(d) (&(d)->decl.reserv)
1082 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1084 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1085 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1086 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1087 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1088 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1089 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1091 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1093 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1094 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1095 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1097 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1098 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1099 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1101 /* Create IR structure (node). */
1102 static void *
1103 create_node (size_t size)
1105 void *result;
1107 obstack_blank (&irp, size);
1108 result = obstack_base (&irp);
1109 obstack_finish (&irp);
1110 /* Default values of members are NULL and zero. */
1111 memset (result, 0, size);
1112 return result;
1115 /* Copy IR structure (node). */
1116 static void *
1117 copy_node (const void *from, size_t size)
1119 void *const result = create_node (size);
1120 memcpy (result, from, size);
1121 return result;
1124 /* The function checks that NAME does not contain quotes (`"'). */
1125 static const char *
1126 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1128 const char *str;
1130 for (str = name; *str != '\0'; str++)
1131 if (*str == '\"')
1132 error ("Name `%s' contains quotes", name);
1133 return name;
1136 /* Pointers to all declarations during IR generation are stored in the
1137 following. */
1138 static vec<decl_t> decls;
1140 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1141 string containing the next separated element, taking parentheses
1142 into account if PAR_FLAG has nonzero value. Advance the pointer to
1143 after the string scanned, or the end-of-string. Return NULL if at
1144 end of string. */
1145 static char *
1146 next_sep_el (const char **pstr, int sep, int par_flag)
1148 char *out_str;
1149 const char *p;
1150 int pars_num;
1151 int n_spaces;
1153 /* Remove leading whitespaces. */
1154 while (ISSPACE ((int) **pstr))
1155 (*pstr)++;
1157 if (**pstr == '\0')
1158 return NULL;
1160 n_spaces = 0;
1161 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1163 if (par_flag && *p == '(')
1164 pars_num++;
1165 else if (par_flag && *p == ')')
1166 pars_num--;
1167 else if (pars_num == 0 && *p == sep)
1168 break;
1169 if (pars_num == 0 && ISSPACE ((int) *p))
1170 n_spaces++;
1171 else
1173 for (; n_spaces != 0; n_spaces--)
1174 obstack_1grow (&irp, p [-n_spaces]);
1175 obstack_1grow (&irp, *p);
1178 obstack_1grow (&irp, '\0');
1179 out_str = (char *) obstack_base (&irp);
1180 obstack_finish (&irp);
1182 *pstr = p;
1183 if (**pstr == sep)
1184 (*pstr)++;
1186 return out_str;
1189 /* Given a string and a separator, return the number of separated
1190 elements in it, taking parentheses into account if PAR_FLAG has
1191 nonzero value. Return 0 for the null string, -1 if parentheses is
1192 not balanced. */
1193 static int
1194 n_sep_els (const char *s, int sep, int par_flag)
1196 int n;
1197 int pars_num;
1199 if (*s == '\0')
1200 return 0;
1202 for (pars_num = 0, n = 1; *s; s++)
1203 if (par_flag && *s == '(')
1204 pars_num++;
1205 else if (par_flag && *s == ')')
1206 pars_num--;
1207 else if (pars_num == 0 && *s == sep)
1208 n++;
1210 return (pars_num != 0 ? -1 : n);
1213 /* Given a string and a separator, return vector of strings which are
1214 elements in the string and number of elements through els_num.
1215 Take parentheses into account if PAREN_P has nonzero value. The
1216 function also inserts the end marker NULL at the end of vector.
1217 Return 0 for the null string, -1 if parentheses are not balanced. */
1218 static char **
1219 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1221 int i;
1222 char **vect;
1223 const char **pstr;
1224 char *trail;
1226 *els_num = n_sep_els (str, sep, paren_p);
1227 if (*els_num <= 0)
1228 return NULL;
1229 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1230 vect = (char **) obstack_base (&irp);
1231 obstack_finish (&irp);
1232 pstr = &str;
1233 for (i = 0; i < *els_num; i++)
1234 vect [i] = next_sep_el (pstr, sep, paren_p);
1235 trail = next_sep_el (pstr, sep, paren_p);
1236 gcc_assert (!trail);
1237 vect [i] = NULL;
1238 return vect;
1241 /* Process a DEFINE_CPU_UNIT.
1243 This gives information about a unit contained in CPU. We fill a
1244 struct unit_decl with information used later by `expand_automata'. */
1245 static void
1246 gen_cpu_unit (rtx def)
1248 decl_t decl;
1249 char **str_cpu_units;
1250 int vect_length;
1251 int i;
1253 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1254 if (str_cpu_units == NULL)
1255 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1256 for (i = 0; i < vect_length; i++)
1258 decl = XCREATENODE (struct decl);
1259 decl->mode = dm_unit;
1260 decl->pos = 0;
1261 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1262 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1263 DECL_UNIT (decl)->query_p = 0;
1264 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1265 DECL_UNIT (decl)->in_set_p = 0;
1266 decls.safe_push (decl);
1270 /* Process a DEFINE_QUERY_CPU_UNIT.
1272 This gives information about a unit contained in CPU. We fill a
1273 struct unit_decl with information used later by `expand_automata'. */
1274 static void
1275 gen_query_cpu_unit (rtx def)
1277 decl_t decl;
1278 char **str_cpu_units;
1279 int vect_length;
1280 int i;
1282 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1283 FALSE);
1284 if (str_cpu_units == NULL)
1285 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1286 for (i = 0; i < vect_length; i++)
1288 decl = XCREATENODE (struct decl);
1289 decl->mode = dm_unit;
1290 decl->pos = 0;
1291 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1292 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1293 DECL_UNIT (decl)->query_p = 1;
1294 decls.safe_push (decl);
1298 /* Process a DEFINE_BYPASS.
1300 This gives information about a unit contained in the CPU. We fill
1301 in a struct bypass_decl with information used later by
1302 `expand_automata'. */
1303 static void
1304 gen_bypass (rtx def)
1306 decl_t decl;
1307 char **out_patterns;
1308 int out_length;
1309 char **in_patterns;
1310 int in_length;
1311 int i, j;
1313 out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1314 if (out_patterns == NULL)
1315 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1316 in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1317 if (in_patterns == NULL)
1318 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1319 for (i = 0; i < out_length; i++)
1320 for (j = 0; j < in_length; j++)
1322 decl = XCREATENODE (struct decl);
1323 decl->mode = dm_bypass;
1324 decl->pos = 0;
1325 DECL_BYPASS (decl)->latency = XINT (def, 0);
1326 DECL_BYPASS (decl)->out_pattern = out_patterns[i];
1327 DECL_BYPASS (decl)->in_pattern = in_patterns[j];
1328 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1329 decls.safe_push (decl);
1333 /* Process an EXCLUSION_SET.
1335 This gives information about a cpu unit conflicts. We fill a
1336 struct excl_rel_decl (excl) with information used later by
1337 `expand_automata'. */
1338 static void
1339 gen_excl_set (rtx def)
1341 decl_t decl;
1342 char **first_str_cpu_units;
1343 char **second_str_cpu_units;
1344 int first_vect_length;
1345 int length;
1346 int i;
1348 first_str_cpu_units
1349 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1350 if (first_str_cpu_units == NULL)
1351 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1352 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1353 FALSE);
1354 if (second_str_cpu_units == NULL)
1355 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1356 length += first_vect_length;
1357 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1358 decl->mode = dm_excl;
1359 decl->pos = 0;
1360 DECL_EXCL (decl)->all_names_num = length;
1361 DECL_EXCL (decl)->first_list_length = first_vect_length;
1362 for (i = 0; i < length; i++)
1363 if (i < first_vect_length)
1364 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1365 else
1366 DECL_EXCL (decl)->names [i]
1367 = second_str_cpu_units [i - first_vect_length];
1368 decls.safe_push (decl);
1371 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1372 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1374 This gives information about a cpu unit reservation requirements.
1375 We fill a struct unit_pattern_rel_decl with information used later
1376 by `expand_automata'. */
1377 static void
1378 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1380 decl_t decl;
1381 char **str_cpu_units;
1382 char **str_pattern_lists;
1383 char ***str_patterns;
1384 int cpu_units_length;
1385 int length;
1386 int patterns_length;
1387 int i;
1389 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1390 FALSE);
1391 if (str_cpu_units == NULL)
1392 fatal ((presence_p
1393 ? (final_p
1394 ? "invalid first string `%s' in final_presence_set"
1395 : "invalid first string `%s' in presence_set")
1396 : (final_p
1397 ? "invalid first string `%s' in final_absence_set"
1398 : "invalid first string `%s' in absence_set")),
1399 XSTR (def, 0));
1400 str_pattern_lists = get_str_vect (XSTR (def, 1),
1401 &patterns_length, ',', FALSE);
1402 if (str_pattern_lists == NULL)
1403 fatal ((presence_p
1404 ? (final_p
1405 ? "invalid second string `%s' in final_presence_set"
1406 : "invalid second string `%s' in presence_set")
1407 : (final_p
1408 ? "invalid second string `%s' in final_absence_set"
1409 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1410 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1411 for (i = 0; i < patterns_length; i++)
1413 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1414 &length, ' ', FALSE);
1415 gcc_assert (str_patterns [i]);
1417 decl = XCREATENODE (struct decl);
1418 decl->pos = 0;
1419 if (presence_p)
1421 decl->mode = dm_presence;
1422 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1423 DECL_PRESENCE (decl)->names = str_cpu_units;
1424 DECL_PRESENCE (decl)->patterns = str_patterns;
1425 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1426 DECL_PRESENCE (decl)->final_p = final_p;
1428 else
1430 decl->mode = dm_absence;
1431 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1432 DECL_ABSENCE (decl)->names = str_cpu_units;
1433 DECL_ABSENCE (decl)->patterns = str_patterns;
1434 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1435 DECL_ABSENCE (decl)->final_p = final_p;
1437 decls.safe_push (decl);
1440 /* Process a PRESENCE_SET.
1442 This gives information about a cpu unit reservation requirements.
1443 We fill a struct unit_pattern_rel_decl (presence) with information
1444 used later by `expand_automata'. */
1445 static void
1446 gen_presence_set (rtx def)
1448 gen_presence_absence_set (def, TRUE, FALSE);
1451 /* Process a FINAL_PRESENCE_SET.
1453 This gives information about a cpu unit reservation requirements.
1454 We fill a struct unit_pattern_rel_decl (presence) with information
1455 used later by `expand_automata'. */
1456 static void
1457 gen_final_presence_set (rtx def)
1459 gen_presence_absence_set (def, TRUE, TRUE);
1462 /* Process an ABSENCE_SET.
1464 This gives information about a cpu unit reservation requirements.
1465 We fill a struct unit_pattern_rel_decl (absence) with information
1466 used later by `expand_automata'. */
1467 static void
1468 gen_absence_set (rtx def)
1470 gen_presence_absence_set (def, FALSE, FALSE);
1473 /* Process a FINAL_ABSENCE_SET.
1475 This gives information about a cpu unit reservation requirements.
1476 We fill a struct unit_pattern_rel_decl (absence) with information
1477 used later by `expand_automata'. */
1478 static void
1479 gen_final_absence_set (rtx def)
1481 gen_presence_absence_set (def, FALSE, TRUE);
1484 /* Process a DEFINE_AUTOMATON.
1486 This gives information about a finite state automaton used for
1487 recognizing pipeline hazards. We fill a struct automaton_decl
1488 with information used later by `expand_automata'. */
1489 static void
1490 gen_automaton (rtx def)
1492 decl_t decl;
1493 char **str_automata;
1494 int vect_length;
1495 int i;
1497 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1498 if (str_automata == NULL)
1499 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1500 for (i = 0; i < vect_length; i++)
1502 decl = XCREATENODE (struct decl);
1503 decl->mode = dm_automaton;
1504 decl->pos = 0;
1505 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1506 decls.safe_push (decl);
1510 /* Process an AUTOMATA_OPTION.
1512 This gives information how to generate finite state automaton used
1513 for recognizing pipeline hazards. */
1514 static void
1515 gen_automata_option (rtx def)
1517 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1518 no_minimization_flag = 1;
1519 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1520 time_flag = 1;
1521 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1522 stats_flag = 1;
1523 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1524 v_flag = 1;
1525 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1526 w_flag = 1;
1527 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1528 ndfa_flag = 1;
1529 else if (strcmp (XSTR (def, 0), COLLAPSE_OPTION + 1) == 0)
1530 collapse_flag = 1;
1531 else if (strcmp (XSTR (def, 0), NO_COMB_OPTION + 1) == 0)
1532 no_comb_flag = 1;
1533 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1534 progress_flag = 1;
1535 else
1536 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1539 /* Name in reservation to denote absence reservation. */
1540 #define NOTHING_NAME "nothing"
1542 /* The following string contains original reservation string being
1543 parsed. */
1544 static const char *reserv_str;
1546 /* Parse an element in STR. */
1547 static regexp_t
1548 gen_regexp_el (const char *str)
1550 regexp_t regexp;
1551 char *dstr;
1552 int len;
1554 if (*str == '(')
1556 len = strlen (str);
1557 if (str [len - 1] != ')')
1558 fatal ("garbage after ) in reservation `%s'", reserv_str);
1559 dstr = XALLOCAVAR (char, len - 1);
1560 memcpy (dstr, str + 1, len - 2);
1561 dstr [len-2] = '\0';
1562 regexp = gen_regexp_sequence (dstr);
1564 else if (strcmp (str, NOTHING_NAME) == 0)
1566 regexp = XCREATENODE (struct regexp);
1567 regexp->mode = rm_nothing;
1569 else
1571 regexp = XCREATENODE (struct regexp);
1572 regexp->mode = rm_unit;
1573 REGEXP_UNIT (regexp)->name = str;
1575 return regexp;
1578 /* Parse construction `repeat' in STR. */
1579 static regexp_t
1580 gen_regexp_repeat (const char *str)
1582 regexp_t regexp;
1583 regexp_t repeat;
1584 char **repeat_vect;
1585 int els_num;
1586 int i;
1588 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1589 if (repeat_vect == NULL)
1590 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1591 if (els_num > 1)
1593 regexp = gen_regexp_el (repeat_vect [0]);
1594 for (i = 1; i < els_num; i++)
1596 repeat = XCREATENODE (struct regexp);
1597 repeat->mode = rm_repeat;
1598 REGEXP_REPEAT (repeat)->regexp = regexp;
1599 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1600 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1601 fatal ("repetition `%s' <= 1 in reservation `%s'",
1602 str, reserv_str);
1603 regexp = repeat;
1605 return regexp;
1607 else
1608 return gen_regexp_el (repeat_vect[0]);
1611 /* Parse reservation STR which possibly contains separator '+'. */
1612 static regexp_t
1613 gen_regexp_allof (const char *str)
1615 regexp_t allof;
1616 char **allof_vect;
1617 int els_num;
1618 int i;
1620 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1621 if (allof_vect == NULL)
1622 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1623 if (els_num > 1)
1625 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1626 + sizeof (regexp_t) * (els_num - 1));
1627 allof->mode = rm_allof;
1628 REGEXP_ALLOF (allof)->regexps_num = els_num;
1629 for (i = 0; i < els_num; i++)
1630 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1631 return allof;
1633 else
1634 return gen_regexp_repeat (allof_vect[0]);
1637 /* Parse reservation STR which possibly contains separator '|'. */
1638 static regexp_t
1639 gen_regexp_oneof (const char *str)
1641 regexp_t oneof;
1642 char **oneof_vect;
1643 int els_num;
1644 int i;
1646 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1647 if (oneof_vect == NULL)
1648 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1649 if (els_num > 1)
1651 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1652 + sizeof (regexp_t) * (els_num - 1));
1653 oneof->mode = rm_oneof;
1654 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1655 for (i = 0; i < els_num; i++)
1656 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1657 return oneof;
1659 else
1660 return gen_regexp_allof (oneof_vect[0]);
1663 /* Parse reservation STR which possibly contains separator ','. */
1664 static regexp_t
1665 gen_regexp_sequence (const char *str)
1667 regexp_t sequence;
1668 char **sequence_vect;
1669 int els_num;
1670 int i;
1672 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1673 if (els_num == -1)
1674 fatal ("unbalanced parentheses in reservation `%s'", str);
1675 if (sequence_vect == NULL)
1676 fatal ("invalid reservation `%s'", str);
1677 if (els_num > 1)
1679 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1680 + sizeof (regexp_t) * (els_num - 1));
1681 sequence->mode = rm_sequence;
1682 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1683 for (i = 0; i < els_num; i++)
1684 REGEXP_SEQUENCE (sequence)->regexps [i]
1685 = gen_regexp_oneof (sequence_vect [i]);
1686 return sequence;
1688 else
1689 return gen_regexp_oneof (sequence_vect[0]);
1692 /* Parse construction reservation STR. */
1693 static regexp_t
1694 gen_regexp (const char *str)
1696 reserv_str = str;
1697 return gen_regexp_sequence (str);
1700 /* Process a DEFINE_RESERVATION.
1702 This gives information about a reservation of cpu units. We fill
1703 in a struct reserv_decl with information used later by
1704 `expand_automata'. */
1705 static void
1706 gen_reserv (rtx def)
1708 decl_t decl;
1710 decl = XCREATENODE (struct decl);
1711 decl->mode = dm_reserv;
1712 decl->pos = 0;
1713 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1714 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1715 decls.safe_push (decl);
1718 /* Process a DEFINE_INSN_RESERVATION.
1720 This gives information about the reservation of cpu units by an
1721 insn. We fill a struct insn_reserv_decl with information used
1722 later by `expand_automata'. */
1723 static void
1724 gen_insn_reserv (rtx def)
1726 decl_t decl;
1728 decl = XCREATENODE (struct decl);
1729 decl->mode = dm_insn_reserv;
1730 decl->pos = 0;
1731 DECL_INSN_RESERV (decl)->name
1732 = check_name (XSTR (def, 0), decl->pos);
1733 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1734 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1735 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1736 decls.safe_push (decl);
1741 /* The function evaluates hash value (0..UINT_MAX) of string. */
1742 static unsigned
1743 string_hash (const char *string)
1745 unsigned result, i;
1747 for (result = i = 0;*string++ != '\0'; i++)
1748 result += ((unsigned char) *string << (i % CHAR_BIT));
1749 return result;
1754 /* This page contains abstract data `table of automaton declarations'.
1755 Elements of the table is nodes representing automaton declarations.
1756 Key of the table elements is name of given automaton. Remember
1757 that automaton names have own space. */
1759 /* The function evaluates hash value of an automaton declaration. The
1760 function is used by abstract data `hashtab'. The function returns
1761 hash value (0..UINT_MAX) of given automaton declaration. */
1762 static hashval_t
1763 automaton_decl_hash (const void *automaton_decl)
1765 const_decl_t const decl = (const_decl_t) automaton_decl;
1767 gcc_assert (decl->mode != dm_automaton
1768 || DECL_AUTOMATON (decl)->name);
1769 return string_hash (DECL_AUTOMATON (decl)->name);
1772 /* The function tests automaton declarations on equality of their
1773 keys. The function is used by abstract data `hashtab'. The
1774 function returns 1 if the declarations have the same key, 0
1775 otherwise. */
1776 static int
1777 automaton_decl_eq_p (const void* automaton_decl_1,
1778 const void* automaton_decl_2)
1780 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1781 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1783 gcc_assert (decl1->mode == dm_automaton
1784 && DECL_AUTOMATON (decl1)->name
1785 && decl2->mode == dm_automaton
1786 && DECL_AUTOMATON (decl2)->name);
1787 return strcmp (DECL_AUTOMATON (decl1)->name,
1788 DECL_AUTOMATON (decl2)->name) == 0;
1791 /* The automaton declaration table itself is represented by the
1792 following variable. */
1793 static htab_t automaton_decl_table;
1795 /* The function inserts automaton declaration into the table. The
1796 function does nothing if an automaton declaration with the same key
1797 exists already in the table. The function returns automaton
1798 declaration node in the table with the same key as given automaton
1799 declaration node. */
1800 static decl_t
1801 insert_automaton_decl (decl_t automaton_decl)
1803 void **entry_ptr;
1805 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1806 if (*entry_ptr == NULL)
1807 *entry_ptr = (void *) automaton_decl;
1808 return (decl_t) *entry_ptr;
1811 /* The following variable value is node representing automaton
1812 declaration. The node used for searching automaton declaration
1813 with given name. */
1814 static struct decl work_automaton_decl;
1816 /* The function searches for automaton declaration in the table with
1817 the same key as node representing name of the automaton
1818 declaration. The function returns node found in the table, NULL if
1819 such node does not exist in the table. */
1820 static decl_t
1821 find_automaton_decl (const char *name)
1823 void *entry;
1825 work_automaton_decl.mode = dm_automaton;
1826 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1827 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1828 return (decl_t) entry;
1831 /* The function creates empty automaton declaration table and node
1832 representing automaton declaration and used for searching automaton
1833 declaration with given name. The function must be called only once
1834 before any work with the automaton declaration table. */
1835 static void
1836 initiate_automaton_decl_table (void)
1838 work_automaton_decl.mode = dm_automaton;
1839 automaton_decl_table = htab_create (10, automaton_decl_hash,
1840 automaton_decl_eq_p, (htab_del) 0);
1843 /* The function deletes the automaton declaration table. Only call of
1844 function `initiate_automaton_decl_table' is possible immediately
1845 after this function call. */
1846 static void
1847 finish_automaton_decl_table (void)
1849 htab_delete (automaton_decl_table);
1854 /* This page contains abstract data `table of insn declarations'.
1855 Elements of the table is nodes representing insn declarations. Key
1856 of the table elements is name of given insn (in corresponding
1857 define_insn_reservation). Remember that insn names have own
1858 space. */
1860 /* The function evaluates hash value of an insn declaration. The
1861 function is used by abstract data `hashtab'. The function returns
1862 hash value (0..UINT_MAX) of given insn declaration. */
1863 static hashval_t
1864 insn_decl_hash (const void *insn_decl)
1866 const_decl_t const decl = (const_decl_t) insn_decl;
1868 gcc_assert (decl->mode == dm_insn_reserv
1869 && DECL_INSN_RESERV (decl)->name);
1870 return string_hash (DECL_INSN_RESERV (decl)->name);
1873 /* The function tests insn declarations on equality of their keys.
1874 The function is used by abstract data `hashtab'. The function
1875 returns 1 if declarations have the same key, 0 otherwise. */
1876 static int
1877 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1879 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1880 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1882 gcc_assert (decl1->mode == dm_insn_reserv
1883 && DECL_INSN_RESERV (decl1)->name
1884 && decl2->mode == dm_insn_reserv
1885 && DECL_INSN_RESERV (decl2)->name);
1886 return strcmp (DECL_INSN_RESERV (decl1)->name,
1887 DECL_INSN_RESERV (decl2)->name) == 0;
1890 /* The insn declaration table itself is represented by the following
1891 variable. The table does not contain insn reservation
1892 declarations. */
1893 static htab_t insn_decl_table;
1895 /* The function inserts insn declaration into the table. The function
1896 does nothing if an insn declaration with the same key exists
1897 already in the table. The function returns insn declaration node
1898 in the table with the same key as given insn declaration node. */
1899 static decl_t
1900 insert_insn_decl (decl_t insn_decl)
1902 void **entry_ptr;
1904 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1905 if (*entry_ptr == NULL)
1906 *entry_ptr = (void *) insn_decl;
1907 return (decl_t) *entry_ptr;
1910 /* The following variable value is node representing insn reservation
1911 declaration. The node used for searching insn reservation
1912 declaration with given name. */
1913 static struct decl work_insn_decl;
1915 /* The function searches for insn reservation declaration in the table
1916 with the same key as node representing name of the insn reservation
1917 declaration. The function returns node found in the table, NULL if
1918 such node does not exist in the table. */
1919 static decl_t
1920 find_insn_decl (const char *name)
1922 void *entry;
1924 work_insn_decl.mode = dm_insn_reserv;
1925 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1926 entry = htab_find (insn_decl_table, &work_insn_decl);
1927 return (decl_t) entry;
1930 /* The function creates empty insn declaration table and node
1931 representing insn declaration and used for searching insn
1932 declaration with given name. The function must be called only once
1933 before any work with the insn declaration table. */
1934 static void
1935 initiate_insn_decl_table (void)
1937 work_insn_decl.mode = dm_insn_reserv;
1938 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1939 (htab_del) 0);
1942 /* The function deletes the insn declaration table. Only call of
1943 function `initiate_insn_decl_table' is possible immediately after
1944 this function call. */
1945 static void
1946 finish_insn_decl_table (void)
1948 htab_delete (insn_decl_table);
1953 /* This page contains abstract data `table of declarations'. Elements
1954 of the table is nodes representing declarations (of units and
1955 reservations). Key of the table elements is names of given
1956 declarations. */
1958 /* The function evaluates hash value of a declaration. The function
1959 is used by abstract data `hashtab'. The function returns hash
1960 value (0..UINT_MAX) of given declaration. */
1961 static hashval_t
1962 decl_hash (const void *decl)
1964 const_decl_t const d = (const_decl_t) decl;
1966 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1967 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1968 return string_hash (d->mode == dm_unit
1969 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1972 /* The function tests declarations on equality of their keys. The
1973 function is used by abstract data 'hashtab'. The function
1974 returns 1 if the declarations have the same key, 0 otherwise. */
1975 static int
1976 decl_eq_p (const void *decl_1, const void *decl_2)
1978 const_decl_t const d1 = (const_decl_t) decl_1;
1979 const_decl_t const d2 = (const_decl_t) decl_2;
1981 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1982 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1983 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1984 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1985 return strcmp ((d1->mode == dm_unit
1986 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1987 (d2->mode == dm_unit
1988 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1991 /* The declaration table itself is represented by the following
1992 variable. */
1993 static htab_t decl_table;
1995 /* The function inserts declaration into the table. The function does
1996 nothing if a declaration with the same key exists already in the
1997 table. The function returns declaration node in the table with the
1998 same key as given declaration node. */
2000 static decl_t
2001 insert_decl (decl_t decl)
2003 void **entry_ptr;
2005 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2006 if (*entry_ptr == NULL)
2007 *entry_ptr = (void *) decl;
2008 return (decl_t) *entry_ptr;
2011 /* The following variable value is node representing declaration. The
2012 node used for searching declaration with given name. */
2013 static struct decl work_decl;
2015 /* The function searches for declaration in the table with the same
2016 key as node representing name of the declaration. The function
2017 returns node found in the table, NULL if such node does not exist
2018 in the table. */
2019 static decl_t
2020 find_decl (const char *name)
2022 void *entry;
2024 work_decl.mode = dm_unit;
2025 DECL_UNIT (&work_decl)->name = name;
2026 entry = htab_find (decl_table, &work_decl);
2027 return (decl_t) entry;
2030 /* The function creates empty declaration table and node representing
2031 declaration and used for searching declaration with given name.
2032 The function must be called only once before any work with the
2033 declaration table. */
2034 static void
2035 initiate_decl_table (void)
2037 work_decl.mode = dm_unit;
2038 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2041 /* The function deletes the declaration table. Only call of function
2042 `initiate_declaration_table' is possible immediately after this
2043 function call. */
2044 static void
2045 finish_decl_table (void)
2047 htab_delete (decl_table);
2052 /* This page contains checker of pipeline hazard description. */
2054 /* Checking NAMES in an exclusion clause vector and returning formed
2055 unit_set_el_list. */
2056 static unit_set_el_t
2057 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2059 unit_set_el_t el_list;
2060 unit_set_el_t last_el;
2061 unit_set_el_t new_el;
2062 decl_t decl_in_table;
2063 int i;
2065 el_list = NULL;
2066 last_el = NULL;
2067 for (i = 0; i < num; i++)
2069 decl_in_table = find_decl (names [i]);
2070 if (decl_in_table == NULL)
2071 error ("unit `%s' in exclusion is not declared", names [i]);
2072 else if (decl_in_table->mode != dm_unit)
2073 error ("`%s' in exclusion is not unit", names [i]);
2074 else
2076 new_el = XCREATENODE (struct unit_set_el);
2077 new_el->unit_decl = DECL_UNIT (decl_in_table);
2078 new_el->next_unit_set_el = NULL;
2079 if (last_el == NULL)
2080 el_list = last_el = new_el;
2081 else
2083 last_el->next_unit_set_el = new_el;
2084 last_el = last_el->next_unit_set_el;
2088 return el_list;
2091 /* The function adds each element from SOURCE_LIST to the exclusion
2092 list of the each element from DEST_LIST. Checking situation "unit
2093 excludes itself". */
2094 static void
2095 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2096 pos_t excl_pos ATTRIBUTE_UNUSED)
2098 unit_set_el_t dst;
2099 unit_set_el_t src;
2100 unit_set_el_t curr_el;
2101 unit_set_el_t prev_el;
2102 unit_set_el_t copy;
2104 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2105 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2107 if (dst->unit_decl == src->unit_decl)
2109 error ("unit `%s' excludes itself", src->unit_decl->name);
2110 continue;
2112 if (dst->unit_decl->automaton_name != NULL
2113 && src->unit_decl->automaton_name != NULL
2114 && strcmp (dst->unit_decl->automaton_name,
2115 src->unit_decl->automaton_name) != 0)
2117 error ("units `%s' and `%s' in exclusion set belong to different automata",
2118 src->unit_decl->name, dst->unit_decl->name);
2119 continue;
2121 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2122 curr_el != NULL;
2123 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2124 if (curr_el->unit_decl == src->unit_decl)
2125 break;
2126 if (curr_el == NULL)
2128 /* Element not found - insert. */
2129 copy = XCOPYNODE (struct unit_set_el, src);
2130 copy->next_unit_set_el = NULL;
2131 if (prev_el == NULL)
2132 dst->unit_decl->excl_list = copy;
2133 else
2134 prev_el->next_unit_set_el = copy;
2139 /* Checking NAMES in presence/absence clause and returning the
2140 formed unit_set_el_list. The function is called only after
2141 processing all exclusion sets. */
2142 static unit_set_el_t
2143 process_presence_absence_names (char **names, int num,
2144 pos_t req_pos ATTRIBUTE_UNUSED,
2145 int presence_p, int final_p)
2147 unit_set_el_t el_list;
2148 unit_set_el_t last_el;
2149 unit_set_el_t new_el;
2150 decl_t decl_in_table;
2151 int i;
2153 el_list = NULL;
2154 last_el = NULL;
2155 for (i = 0; i < num; i++)
2157 decl_in_table = find_decl (names [i]);
2158 if (decl_in_table == NULL)
2159 error ((presence_p
2160 ? (final_p
2161 ? "unit `%s' in final presence set is not declared"
2162 : "unit `%s' in presence set is not declared")
2163 : (final_p
2164 ? "unit `%s' in final absence set is not declared"
2165 : "unit `%s' in absence set is not declared")), names [i]);
2166 else if (decl_in_table->mode != dm_unit)
2167 error ((presence_p
2168 ? (final_p
2169 ? "`%s' in final presence set is not unit"
2170 : "`%s' in presence set is not unit")
2171 : (final_p
2172 ? "`%s' in final absence set is not unit"
2173 : "`%s' in absence set is not unit")), names [i]);
2174 else
2176 new_el = XCREATENODE (struct unit_set_el);
2177 new_el->unit_decl = DECL_UNIT (decl_in_table);
2178 new_el->next_unit_set_el = NULL;
2179 if (last_el == NULL)
2180 el_list = last_el = new_el;
2181 else
2183 last_el->next_unit_set_el = new_el;
2184 last_el = last_el->next_unit_set_el;
2188 return el_list;
2191 /* Checking NAMES in patterns of a presence/absence clause and
2192 returning the formed pattern_set_el_list. The function is called
2193 only after processing all exclusion sets. */
2194 static pattern_set_el_t
2195 process_presence_absence_patterns (char ***patterns, int num,
2196 pos_t req_pos ATTRIBUTE_UNUSED,
2197 int presence_p, int final_p)
2199 pattern_set_el_t el_list;
2200 pattern_set_el_t last_el;
2201 pattern_set_el_t new_el;
2202 decl_t decl_in_table;
2203 int i, j;
2205 el_list = NULL;
2206 last_el = NULL;
2207 for (i = 0; i < num; i++)
2209 for (j = 0; patterns [i] [j] != NULL; j++)
2211 new_el = XCREATENODEVAR (struct pattern_set_el,
2212 sizeof (struct pattern_set_el)
2213 + sizeof (struct unit_decl *) * j);
2214 new_el->unit_decls
2215 = (struct unit_decl **) ((char *) new_el
2216 + sizeof (struct pattern_set_el));
2217 new_el->next_pattern_set_el = NULL;
2218 if (last_el == NULL)
2219 el_list = last_el = new_el;
2220 else
2222 last_el->next_pattern_set_el = new_el;
2223 last_el = last_el->next_pattern_set_el;
2225 new_el->units_num = 0;
2226 for (j = 0; patterns [i] [j] != NULL; j++)
2228 decl_in_table = find_decl (patterns [i] [j]);
2229 if (decl_in_table == NULL)
2230 error ((presence_p
2231 ? (final_p
2232 ? "unit `%s' in final presence set is not declared"
2233 : "unit `%s' in presence set is not declared")
2234 : (final_p
2235 ? "unit `%s' in final absence set is not declared"
2236 : "unit `%s' in absence set is not declared")),
2237 patterns [i] [j]);
2238 else if (decl_in_table->mode != dm_unit)
2239 error ((presence_p
2240 ? (final_p
2241 ? "`%s' in final presence set is not unit"
2242 : "`%s' in presence set is not unit")
2243 : (final_p
2244 ? "`%s' in final absence set is not unit"
2245 : "`%s' in absence set is not unit")),
2246 patterns [i] [j]);
2247 else
2249 new_el->unit_decls [new_el->units_num]
2250 = DECL_UNIT (decl_in_table);
2251 new_el->units_num++;
2255 return el_list;
2258 /* The function adds each element from PATTERN_LIST to presence (if
2259 PRESENCE_P) or absence list of the each element from DEST_LIST.
2260 Checking situations "unit requires own absence", and "unit excludes
2261 and requires presence of ...", "unit requires absence and presence
2262 of ...", "units in (final) presence set belong to different
2263 automata", and "units in (final) absence set belong to different
2264 automata". Remember that we process absence sets only after all
2265 presence sets. */
2266 static void
2267 add_presence_absence (unit_set_el_t dest_list,
2268 pattern_set_el_t pattern_list,
2269 pos_t req_pos ATTRIBUTE_UNUSED,
2270 int presence_p, int final_p)
2272 unit_set_el_t dst;
2273 pattern_set_el_t pat;
2274 struct unit_decl *unit;
2275 unit_set_el_t curr_excl_el;
2276 pattern_set_el_t curr_pat_el;
2277 pattern_set_el_t prev_el;
2278 pattern_set_el_t copy;
2279 int i;
2280 int no_error_flag;
2282 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2283 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2285 for (i = 0; i < pat->units_num; i++)
2287 unit = pat->unit_decls [i];
2288 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2290 error ("unit `%s' requires own absence", unit->name);
2291 continue;
2293 if (dst->unit_decl->automaton_name != NULL
2294 && unit->automaton_name != NULL
2295 && strcmp (dst->unit_decl->automaton_name,
2296 unit->automaton_name) != 0)
2298 error ((presence_p
2299 ? (final_p
2300 ? "units `%s' and `%s' in final presence set belong to different automata"
2301 : "units `%s' and `%s' in presence set belong to different automata")
2302 : (final_p
2303 ? "units `%s' and `%s' in final absence set belong to different automata"
2304 : "units `%s' and `%s' in absence set belong to different automata")),
2305 unit->name, dst->unit_decl->name);
2306 continue;
2308 no_error_flag = 1;
2309 if (presence_p)
2310 for (curr_excl_el = dst->unit_decl->excl_list;
2311 curr_excl_el != NULL;
2312 curr_excl_el = curr_excl_el->next_unit_set_el)
2314 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2316 if (!w_flag)
2318 error ("unit `%s' excludes and requires presence of `%s'",
2319 dst->unit_decl->name, unit->name);
2320 no_error_flag = 0;
2322 else
2323 warning ("unit `%s' excludes and requires presence of `%s'",
2324 dst->unit_decl->name, unit->name);
2327 else if (pat->units_num == 1)
2328 for (curr_pat_el = dst->unit_decl->presence_list;
2329 curr_pat_el != NULL;
2330 curr_pat_el = curr_pat_el->next_pattern_set_el)
2331 if (curr_pat_el->units_num == 1
2332 && unit == curr_pat_el->unit_decls [0])
2334 if (!w_flag)
2336 error ("unit `%s' requires absence and presence of `%s'",
2337 dst->unit_decl->name, unit->name);
2338 no_error_flag = 0;
2340 else
2341 warning ("unit `%s' requires absence and presence of `%s'",
2342 dst->unit_decl->name, unit->name);
2344 if (no_error_flag)
2346 for (prev_el = (presence_p
2347 ? (final_p
2348 ? dst->unit_decl->final_presence_list
2349 : dst->unit_decl->presence_list)
2350 : (final_p
2351 ? dst->unit_decl->final_absence_list
2352 : dst->unit_decl->absence_list));
2353 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2354 prev_el = prev_el->next_pattern_set_el)
2356 copy = XCOPYNODE (struct pattern_set_el, pat);
2357 copy->next_pattern_set_el = NULL;
2358 if (prev_el == NULL)
2360 if (presence_p)
2362 if (final_p)
2363 dst->unit_decl->final_presence_list = copy;
2364 else
2365 dst->unit_decl->presence_list = copy;
2367 else if (final_p)
2368 dst->unit_decl->final_absence_list = copy;
2369 else
2370 dst->unit_decl->absence_list = copy;
2372 else
2373 prev_el->next_pattern_set_el = copy;
2380 /* The function inserts BYPASS in the list of bypasses of the
2381 corresponding output insn. The order of bypasses in the list is
2382 described in a comment for member `bypass_list' (see above). If
2383 there is already the same bypass in the list the function reports
2384 this and does nothing. */
2385 static void
2386 insert_bypass (struct bypass_decl *bypass)
2388 struct bypass_decl *curr, *last;
2389 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2390 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2392 for (curr = out_insn_reserv->bypass_list, last = NULL;
2393 curr != NULL;
2394 last = curr, curr = curr->next)
2395 if (curr->in_insn_reserv == in_insn_reserv)
2397 if ((bypass->bypass_guard_name != NULL
2398 && curr->bypass_guard_name != NULL
2399 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2400 || bypass->bypass_guard_name == curr->bypass_guard_name)
2402 if (bypass->bypass_guard_name == NULL)
2404 if (!w_flag)
2405 error ("the same bypass `%s - %s' is already defined",
2406 bypass->out_pattern, bypass->in_pattern);
2407 else
2408 warning ("the same bypass `%s - %s' is already defined",
2409 bypass->out_pattern, bypass->in_pattern);
2411 else if (!w_flag)
2412 error ("the same bypass `%s - %s' (guard %s) is already defined",
2413 bypass->out_pattern, bypass->in_pattern,
2414 bypass->bypass_guard_name);
2415 else
2416 warning
2417 ("the same bypass `%s - %s' (guard %s) is already defined",
2418 bypass->out_pattern, bypass->in_pattern,
2419 bypass->bypass_guard_name);
2420 return;
2422 if (curr->bypass_guard_name == NULL)
2423 break;
2424 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2426 last = curr;
2427 break;
2431 if (last == NULL)
2433 bypass->next = out_insn_reserv->bypass_list;
2434 out_insn_reserv->bypass_list = bypass;
2436 else
2438 bypass->next = last->next;
2439 last->next = bypass;
2443 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2444 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2446 static void
2447 for_each_matching_insn (decl_t bypass, const char *pattern,
2448 void (*fn) (decl_t, decl_t, void *), void *data)
2450 decl_t insn_reserv;
2451 bool matched_p;
2452 int i;
2454 matched_p = false;
2455 if (strpbrk (pattern, "*?["))
2456 for (i = 0; i < description->decls_num; i++)
2458 insn_reserv = description->decls[i];
2459 if (insn_reserv->mode == dm_insn_reserv
2460 && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
2462 fn (bypass, insn_reserv, data);
2463 matched_p = true;
2466 else
2468 insn_reserv = find_insn_decl (pattern);
2469 if (insn_reserv)
2471 fn (bypass, insn_reserv, data);
2472 matched_p = true;
2475 if (!matched_p)
2476 error ("there is no insn reservation that matches `%s'", pattern);
2479 /* A subroutine of process_bypass that is called for each pair
2480 of matching instructions. OUT_INSN_RESERV is the output
2481 instruction and DATA is the input instruction. */
2483 static void
2484 process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
2486 struct bypass_decl *bypass;
2487 decl_t in_insn_reserv;
2489 in_insn_reserv = (decl_t) data;
2490 if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
2491 DECL_BYPASS (model)->in_pattern) == 0
2492 && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
2493 DECL_BYPASS (model)->out_pattern) == 0)
2494 bypass = DECL_BYPASS (model);
2495 else
2497 bypass = XCNEW (struct bypass_decl);
2498 bypass->latency = DECL_BYPASS (model)->latency;
2499 bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
2500 bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
2501 bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
2503 bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
2504 bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
2505 insert_bypass (bypass);
2508 /* A subroutine of process_bypass that is called for each input
2509 instruction IN_INSN_RESERV. */
2511 static void
2512 process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
2513 void *data ATTRIBUTE_UNUSED)
2515 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
2516 process_bypass_2, in_insn_reserv);
2519 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2520 pair of insn reservations. */
2522 static void
2523 process_bypass (decl_t bypass)
2525 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
2526 process_bypass_1, NULL);
2529 /* The function processes pipeline description declarations, checks
2530 their correctness, and forms exclusion/presence/absence sets. */
2531 static void
2532 process_decls (void)
2534 decl_t decl;
2535 decl_t automaton_decl;
2536 decl_t decl_in_table;
2537 int automaton_presence;
2538 int i;
2540 /* Checking repeated automata declarations. */
2541 automaton_presence = 0;
2542 for (i = 0; i < description->decls_num; i++)
2544 decl = description->decls [i];
2545 if (decl->mode == dm_automaton)
2547 automaton_presence = 1;
2548 decl_in_table = insert_automaton_decl (decl);
2549 if (decl_in_table != decl)
2551 if (!w_flag)
2552 error ("repeated declaration of automaton `%s'",
2553 DECL_AUTOMATON (decl)->name);
2554 else
2555 warning ("repeated declaration of automaton `%s'",
2556 DECL_AUTOMATON (decl)->name);
2560 /* Checking undeclared automata, repeated declarations (except for
2561 automata) and correctness of their attributes (insn latency times
2562 etc.). */
2563 for (i = 0; i < description->decls_num; i++)
2565 decl = description->decls [i];
2566 if (decl->mode == dm_insn_reserv)
2568 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2569 error ("define_insn_reservation `%s' has negative latency time",
2570 DECL_INSN_RESERV (decl)->name);
2571 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2572 description->insns_num++;
2573 decl_in_table = insert_insn_decl (decl);
2574 if (decl_in_table != decl)
2575 error ("`%s' is already used as insn reservation name",
2576 DECL_INSN_RESERV (decl)->name);
2578 else if (decl->mode == dm_bypass)
2580 if (DECL_BYPASS (decl)->latency < 0)
2581 error ("define_bypass `%s - %s' has negative latency time",
2582 DECL_BYPASS (decl)->out_pattern,
2583 DECL_BYPASS (decl)->in_pattern);
2585 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2587 if (decl->mode == dm_unit)
2589 DECL_UNIT (decl)->automaton_decl = NULL;
2590 if (DECL_UNIT (decl)->automaton_name != NULL)
2592 automaton_decl
2593 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2594 if (automaton_decl == NULL)
2595 error ("automaton `%s' is not declared",
2596 DECL_UNIT (decl)->automaton_name);
2597 else
2599 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2600 DECL_UNIT (decl)->automaton_decl
2601 = DECL_AUTOMATON (automaton_decl);
2604 else if (automaton_presence)
2605 error ("define_unit `%s' without automaton when one defined",
2606 DECL_UNIT (decl)->name);
2607 DECL_UNIT (decl)->unit_num = description->units_num;
2608 description->units_num++;
2609 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2611 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2612 continue;
2614 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2616 else
2618 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2620 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2621 continue;
2623 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2625 if (decl_in_table == NULL)
2626 decl_in_table = insert_decl (decl);
2627 else
2629 if (decl->mode == dm_unit)
2630 error ("repeated declaration of unit `%s'",
2631 DECL_UNIT (decl)->name);
2632 else
2633 error ("repeated declaration of reservation `%s'",
2634 DECL_RESERV (decl)->name);
2638 /* Check bypasses and form list of bypasses for each (output)
2639 insn. */
2640 for (i = 0; i < description->decls_num; i++)
2642 decl = description->decls [i];
2643 if (decl->mode == dm_bypass)
2644 process_bypass (decl);
2647 /* Check exclusion set declarations and form exclusion sets. */
2648 for (i = 0; i < description->decls_num; i++)
2650 decl = description->decls [i];
2651 if (decl->mode == dm_excl)
2653 unit_set_el_t unit_set_el_list;
2654 unit_set_el_t unit_set_el_list_2;
2656 unit_set_el_list
2657 = process_excls (DECL_EXCL (decl)->names,
2658 DECL_EXCL (decl)->first_list_length, decl->pos);
2659 unit_set_el_list_2
2660 = process_excls (&DECL_EXCL (decl)->names
2661 [DECL_EXCL (decl)->first_list_length],
2662 DECL_EXCL (decl)->all_names_num
2663 - DECL_EXCL (decl)->first_list_length,
2664 decl->pos);
2665 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2666 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2670 /* Check presence set declarations and form presence sets. */
2671 for (i = 0; i < description->decls_num; i++)
2673 decl = description->decls [i];
2674 if (decl->mode == dm_presence)
2676 unit_set_el_t unit_set_el_list;
2677 pattern_set_el_t pattern_set_el_list;
2679 unit_set_el_list
2680 = process_presence_absence_names
2681 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2682 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2683 pattern_set_el_list
2684 = process_presence_absence_patterns
2685 (DECL_PRESENCE (decl)->patterns,
2686 DECL_PRESENCE (decl)->patterns_num,
2687 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2688 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2689 decl->pos, TRUE,
2690 DECL_PRESENCE (decl)->final_p);
2694 /* Check absence set declarations and form absence sets. */
2695 for (i = 0; i < description->decls_num; i++)
2697 decl = description->decls [i];
2698 if (decl->mode == dm_absence)
2700 unit_set_el_t unit_set_el_list;
2701 pattern_set_el_t pattern_set_el_list;
2703 unit_set_el_list
2704 = process_presence_absence_names
2705 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2706 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2707 pattern_set_el_list
2708 = process_presence_absence_patterns
2709 (DECL_ABSENCE (decl)->patterns,
2710 DECL_ABSENCE (decl)->patterns_num,
2711 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2712 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2713 decl->pos, FALSE,
2714 DECL_ABSENCE (decl)->final_p);
2719 /* The following function checks that declared automaton is used. If
2720 the automaton is not used, the function fixes error/warning. The
2721 following function must be called only after `process_decls'. */
2722 static void
2723 check_automaton_usage (void)
2725 decl_t decl;
2726 int i;
2728 for (i = 0; i < description->decls_num; i++)
2730 decl = description->decls [i];
2731 if (decl->mode == dm_automaton
2732 && !DECL_AUTOMATON (decl)->automaton_is_used)
2734 if (!w_flag)
2735 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2736 else
2737 warning ("automaton `%s' is not used",
2738 DECL_AUTOMATON (decl)->name);
2743 /* The following recursive function processes all regexp in order to
2744 fix usage of units or reservations and to fix errors of undeclared
2745 name. The function may change unit_regexp onto reserv_regexp.
2746 Remember that reserv_regexp does not exist before the function
2747 call. */
2748 static regexp_t
2749 process_regexp (regexp_t regexp)
2751 decl_t decl_in_table;
2752 regexp_t new_regexp;
2753 int i;
2755 switch (regexp->mode)
2757 case rm_unit:
2758 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2759 if (decl_in_table == NULL)
2760 error ("undeclared unit or reservation `%s'",
2761 REGEXP_UNIT (regexp)->name);
2762 else
2763 switch (decl_in_table->mode)
2765 case dm_unit:
2766 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2767 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2768 break;
2770 case dm_reserv:
2771 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2772 new_regexp = XCREATENODE (struct regexp);
2773 new_regexp->mode = rm_reserv;
2774 new_regexp->pos = regexp->pos;
2775 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2776 REGEXP_RESERV (new_regexp)->reserv_decl
2777 = DECL_RESERV (decl_in_table);
2778 regexp = new_regexp;
2779 break;
2781 default:
2782 gcc_unreachable ();
2784 break;
2785 case rm_sequence:
2786 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2787 REGEXP_SEQUENCE (regexp)->regexps [i]
2788 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2789 break;
2790 case rm_allof:
2791 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2792 REGEXP_ALLOF (regexp)->regexps [i]
2793 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2794 break;
2795 case rm_oneof:
2796 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2797 REGEXP_ONEOF (regexp)->regexps [i]
2798 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2799 break;
2800 case rm_repeat:
2801 REGEXP_REPEAT (regexp)->regexp
2802 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2803 break;
2804 case rm_nothing:
2805 break;
2806 default:
2807 gcc_unreachable ();
2809 return regexp;
2812 /* The following function processes regexp of define_reservation and
2813 define_insn_reservation with the aid of function
2814 `process_regexp'. */
2815 static void
2816 process_regexp_decls (void)
2818 decl_t decl;
2819 int i;
2821 for (i = 0; i < description->decls_num; i++)
2823 decl = description->decls [i];
2824 if (decl->mode == dm_reserv)
2825 DECL_RESERV (decl)->regexp
2826 = process_regexp (DECL_RESERV (decl)->regexp);
2827 else if (decl->mode == dm_insn_reserv)
2828 DECL_INSN_RESERV (decl)->regexp
2829 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2833 /* The following function checks that declared unit is used. If the
2834 unit is not used, the function fixes errors/warnings. The
2835 following function must be called only after `process_decls',
2836 `process_regexp_decls'. */
2837 static void
2838 check_usage (void)
2840 decl_t decl;
2841 int i;
2843 for (i = 0; i < description->decls_num; i++)
2845 decl = description->decls [i];
2846 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2848 if (!w_flag)
2849 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2850 else
2851 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2853 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2855 if (!w_flag)
2856 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2857 else
2858 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2863 /* The following variable value is number of reservation being
2864 processed on loop recognition. */
2865 static int curr_loop_pass_num;
2867 /* The following recursive function returns nonzero value if REGEXP
2868 contains given decl or reservations in given regexp refers for
2869 given decl. */
2870 static int
2871 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2873 int i;
2875 if (regexp == NULL)
2876 return 0;
2877 switch (regexp->mode)
2879 case rm_unit:
2880 return 0;
2882 case rm_reserv:
2883 if (start_decl->mode == dm_reserv
2884 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2885 return 1;
2886 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2887 == curr_loop_pass_num)
2888 /* declaration has been processed. */
2889 return 0;
2890 else
2892 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2893 = curr_loop_pass_num;
2894 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2895 start_decl);
2898 case rm_sequence:
2899 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2900 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2901 return 1;
2902 return 0;
2904 case rm_allof:
2905 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2906 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2907 return 1;
2908 return 0;
2910 case rm_oneof:
2911 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2912 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2913 return 1;
2914 return 0;
2916 case rm_repeat:
2917 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2919 case rm_nothing:
2920 return 0;
2922 default:
2923 gcc_unreachable ();
2927 /* The following function fixes errors "cycle in definition ...". The
2928 function uses function `loop_in_regexp' for that. */
2929 static void
2930 check_loops_in_regexps (void)
2932 decl_t decl;
2933 int i;
2935 for (i = 0; i < description->decls_num; i++)
2937 decl = description->decls [i];
2938 if (decl->mode == dm_reserv)
2939 DECL_RESERV (decl)->loop_pass_num = 0;
2941 for (i = 0; i < description->decls_num; i++)
2943 decl = description->decls [i];
2944 curr_loop_pass_num = i;
2946 if (decl->mode == dm_reserv)
2948 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2949 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2951 gcc_assert (DECL_RESERV (decl)->regexp);
2952 error ("cycle in definition of reservation `%s'",
2953 DECL_RESERV (decl)->name);
2959 /* The function recursively processes IR of reservation and defines
2960 max and min cycle for reservation of unit. */
2961 static void
2962 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2963 int min_start_cycle, int *max_finish_cycle,
2964 int *min_finish_cycle)
2966 int i;
2968 switch (regexp->mode)
2970 case rm_unit:
2971 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2972 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2973 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2974 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2975 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2976 *max_finish_cycle = max_start_cycle;
2977 *min_finish_cycle = min_start_cycle;
2978 break;
2980 case rm_reserv:
2981 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2982 max_start_cycle, min_start_cycle,
2983 max_finish_cycle, min_finish_cycle);
2984 break;
2986 case rm_repeat:
2987 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2989 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2990 max_start_cycle, min_start_cycle,
2991 max_finish_cycle, min_finish_cycle);
2992 max_start_cycle = *max_finish_cycle + 1;
2993 min_start_cycle = *min_finish_cycle + 1;
2995 break;
2997 case rm_sequence:
2998 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3000 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3001 max_start_cycle, min_start_cycle,
3002 max_finish_cycle, min_finish_cycle);
3003 max_start_cycle = *max_finish_cycle + 1;
3004 min_start_cycle = *min_finish_cycle + 1;
3006 break;
3008 case rm_allof:
3010 int max_cycle = 0;
3011 int min_cycle = 0;
3013 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3015 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3016 max_start_cycle, min_start_cycle,
3017 max_finish_cycle, min_finish_cycle);
3018 if (max_cycle < *max_finish_cycle)
3019 max_cycle = *max_finish_cycle;
3020 if (i == 0 || min_cycle > *min_finish_cycle)
3021 min_cycle = *min_finish_cycle;
3023 *max_finish_cycle = max_cycle;
3024 *min_finish_cycle = min_cycle;
3026 break;
3028 case rm_oneof:
3030 int max_cycle = 0;
3031 int min_cycle = 0;
3033 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3035 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3036 max_start_cycle, min_start_cycle,
3037 max_finish_cycle, min_finish_cycle);
3038 if (max_cycle < *max_finish_cycle)
3039 max_cycle = *max_finish_cycle;
3040 if (i == 0 || min_cycle > *min_finish_cycle)
3041 min_cycle = *min_finish_cycle;
3043 *max_finish_cycle = max_cycle;
3044 *min_finish_cycle = min_cycle;
3046 break;
3048 case rm_nothing:
3049 *max_finish_cycle = max_start_cycle;
3050 *min_finish_cycle = min_start_cycle;
3051 break;
3053 default:
3054 gcc_unreachable ();
3058 /* The following function is called only for correct program. The
3059 function defines max reservation of insns in cycles. */
3060 static void
3061 evaluate_max_reserv_cycles (void)
3063 int max_insn_cycles_num;
3064 int min_insn_cycles_num;
3065 decl_t decl;
3066 int i;
3068 description->max_insn_reserv_cycles = 0;
3069 for (i = 0; i < description->decls_num; i++)
3071 decl = description->decls [i];
3072 if (decl->mode == dm_insn_reserv)
3074 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3075 &max_insn_cycles_num, &min_insn_cycles_num);
3076 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3077 description->max_insn_reserv_cycles = max_insn_cycles_num;
3080 description->max_insn_reserv_cycles++;
3083 /* The following function calls functions for checking all
3084 description. */
3085 static void
3086 check_all_description (void)
3088 process_decls ();
3089 check_automaton_usage ();
3090 process_regexp_decls ();
3091 check_usage ();
3092 check_loops_in_regexps ();
3093 if (!have_error)
3094 evaluate_max_reserv_cycles ();
3099 /* The page contains abstract data `ticker'. This data is used to
3100 report time of different phases of building automata. It is
3101 possibly to write a description for which automata will be built
3102 during several minutes even on fast machine. */
3104 /* The following function creates ticker and makes it active. */
3105 static ticker_t
3106 create_ticker (void)
3108 ticker_t ticker;
3110 ticker.modified_creation_time = get_run_time ();
3111 ticker.incremented_off_time = 0;
3112 return ticker;
3115 /* The following function switches off given ticker. */
3116 static void
3117 ticker_off (ticker_t *ticker)
3119 if (ticker->incremented_off_time == 0)
3120 ticker->incremented_off_time = get_run_time () + 1;
3123 /* The following function switches on given ticker. */
3124 static void
3125 ticker_on (ticker_t *ticker)
3127 if (ticker->incremented_off_time != 0)
3129 ticker->modified_creation_time
3130 += get_run_time () - ticker->incremented_off_time + 1;
3131 ticker->incremented_off_time = 0;
3135 /* The following function returns current time in milliseconds since
3136 the moment when given ticker was created. */
3137 static int
3138 active_time (ticker_t ticker)
3140 if (ticker.incremented_off_time != 0)
3141 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3142 else
3143 return get_run_time () - ticker.modified_creation_time;
3146 /* The following function returns string representation of active time
3147 of given ticker. The result is string representation of seconds
3148 with accuracy of 1/100 second. Only result of the last call of the
3149 function exists. Therefore the following code is not correct
3151 printf ("parser time: %s\ngeneration time: %s\n",
3152 active_time_string (parser_ticker),
3153 active_time_string (generation_ticker));
3155 Correct code has to be the following
3157 printf ("parser time: %s\n", active_time_string (parser_ticker));
3158 printf ("generation time: %s\n",
3159 active_time_string (generation_ticker));
3162 static void
3163 print_active_time (FILE *f, ticker_t ticker)
3165 int msecs;
3167 msecs = active_time (ticker);
3168 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3173 /* The following variable value is number of automaton which are
3174 really being created. This value is defined on the base of
3175 argument of option `-split'. If the variable has zero value the
3176 number of automata is defined by the constructions `%automaton'.
3177 This case occurs when option `-split' is absent or has zero
3178 argument. If constructions `define_automaton' is absent only one
3179 automaton is created. */
3180 static int automata_num;
3182 /* The following variable values are times of
3183 o transformation of regular expressions
3184 o building NDFA (DFA if !ndfa_flag)
3185 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3186 o DFA minimization
3187 o building insn equivalence classes
3188 o all previous ones
3189 o code output */
3190 static ticker_t transform_time;
3191 static ticker_t NDFA_time;
3192 static ticker_t NDFA_to_DFA_time;
3193 static ticker_t minimize_time;
3194 static ticker_t equiv_time;
3195 static ticker_t automaton_generation_time;
3196 static ticker_t output_time;
3198 /* The following variable values are times of
3199 all checking
3200 all generation
3201 all pipeline hazard translator work */
3202 static ticker_t check_time;
3203 static ticker_t generation_time;
3204 static ticker_t all_time;
3208 /* Pseudo insn decl which denotes advancing cycle. */
3209 static decl_t advance_cycle_insn_decl;
3210 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3211 static decl_t collapse_ndfa_insn_decl;
3213 /* Create and record a decl for the special advance-cycle transition. */
3214 static void
3215 add_advance_cycle_insn_decl (void)
3217 advance_cycle_insn_decl = XCREATENODE (struct decl);
3218 advance_cycle_insn_decl->mode = dm_insn_reserv;
3219 advance_cycle_insn_decl->pos = no_pos;
3220 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3221 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3222 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3223 = description->insns_num;
3224 description->decls [description->decls_num] = advance_cycle_insn_decl;
3225 description->decls_num++;
3226 description->insns_num++;
3229 /* Create and record a decl for the special collapse-NDFA transition. */
3230 static void
3231 add_collapse_ndfa_insn_decl (void)
3233 collapse_ndfa_insn_decl = XCREATENODE (struct decl);
3234 collapse_ndfa_insn_decl->mode = dm_insn_reserv;
3235 collapse_ndfa_insn_decl->pos = no_pos;
3236 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
3237 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
3238 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
3239 = description->insns_num;
3240 description->decls [description->decls_num] = collapse_ndfa_insn_decl;
3241 description->decls_num++;
3242 description->insns_num++;
3245 /* True if DECL is either of the two special decls we created. */
3246 static bool
3247 special_decl_p (struct insn_reserv_decl *decl)
3249 return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
3250 || (collapse_flag
3251 && decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
3255 /* Abstract data `alternative states' which represents
3256 nondeterministic nature of the description (see comments for
3257 structures alt_state and state). */
3259 /* List of free states. */
3260 static alt_state_t first_free_alt_state;
3262 #ifndef NDEBUG
3263 /* The following variables is maximal number of allocated nodes
3264 alt_state. */
3265 static int allocated_alt_states_num = 0;
3266 #endif
3268 /* The following function returns free node alt_state. It may be new
3269 allocated node or node freed earlier. */
3270 static alt_state_t
3271 get_free_alt_state (void)
3273 alt_state_t result;
3275 if (first_free_alt_state != NULL)
3277 result = first_free_alt_state;
3278 first_free_alt_state = first_free_alt_state->next_alt_state;
3280 else
3282 #ifndef NDEBUG
3283 allocated_alt_states_num++;
3284 #endif
3285 result = XCREATENODE (struct alt_state);
3287 result->state = NULL;
3288 result->next_alt_state = NULL;
3289 result->next_sorted_alt_state = NULL;
3290 return result;
3293 /* The function frees node ALT_STATE. */
3294 static void
3295 free_alt_state (alt_state_t alt_state)
3297 if (alt_state == NULL)
3298 return;
3299 alt_state->next_alt_state = first_free_alt_state;
3300 first_free_alt_state = alt_state;
3303 /* The function frees list started with node ALT_STATE_LIST. */
3304 static void
3305 free_alt_states (alt_state_t alt_states_list)
3307 alt_state_t curr_alt_state;
3308 alt_state_t next_alt_state;
3310 for (curr_alt_state = alt_states_list;
3311 curr_alt_state != NULL;
3312 curr_alt_state = next_alt_state)
3314 next_alt_state = curr_alt_state->next_alt_state;
3315 free_alt_state (curr_alt_state);
3319 /* The function compares unique numbers of alt states. */
3320 static int
3321 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3323 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3324 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3325 return 0;
3326 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3327 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3328 return -1;
3329 else
3330 return 1;
3333 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3334 states from the list. The comparison key is alt state unique
3335 number. */
3337 static alt_state_t
3338 uniq_sort_alt_states (alt_state_t alt_states_list)
3340 alt_state_t curr_alt_state;
3341 size_t i;
3342 size_t prev_unique_state_ind;
3343 alt_state_t result;
3345 if (alt_states_list == 0)
3346 return 0;
3347 if (alt_states_list->next_alt_state == 0)
3348 return alt_states_list;
3350 auto_vec<alt_state_t, 150> alt_states;
3351 for (curr_alt_state = alt_states_list;
3352 curr_alt_state != NULL;
3353 curr_alt_state = curr_alt_state->next_alt_state)
3354 alt_states.safe_push (curr_alt_state);
3356 alt_states.qsort (alt_state_cmp);
3358 prev_unique_state_ind = 0;
3359 for (i = 1; i < alt_states.length (); i++)
3360 if (alt_states[prev_unique_state_ind]->state != alt_states[i]->state)
3362 prev_unique_state_ind++;
3363 alt_states[prev_unique_state_ind] = alt_states[i];
3365 alt_states.truncate (prev_unique_state_ind + 1);
3367 for (i = 1; i < alt_states.length (); i++)
3368 alt_states[i-1]->next_sorted_alt_state
3369 = alt_states[i];
3370 alt_states.last ()->next_sorted_alt_state = 0;
3372 result = alt_states[0];
3374 return result;
3377 /* The function checks equality of alt state lists. Remember that the
3378 lists must be already sorted by the previous function. */
3379 static int
3380 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3382 while (alt_states_1 != NULL && alt_states_2 != NULL
3383 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3385 alt_states_1 = alt_states_1->next_sorted_alt_state;
3386 alt_states_2 = alt_states_2->next_sorted_alt_state;
3388 return alt_states_1 == alt_states_2;
3391 /* Initialization of the abstract data. */
3392 static void
3393 initiate_alt_states (void)
3395 first_free_alt_state = NULL;
3398 /* Finishing work with the abstract data. */
3399 static void
3400 finish_alt_states (void)
3406 /* The page contains macros for work with bits strings. We could use
3407 standard gcc bitmap or sbitmap but it would result in difficulties
3408 of building canadian cross. */
3410 /* Set bit number bitno in the bit string. The macro is not side
3411 effect proof. */
3412 #define bitmap_set_bit(bitstring, bitno) \
3413 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3414 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3416 #define CLEAR_BIT(bitstring, bitno) \
3417 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3418 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3420 /* Test if bit number bitno in the bitstring is set. The macro is not
3421 side effect proof. */
3422 #define bitmap_bit_p(bitstring, bitno) \
3423 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3424 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3428 /* This page contains abstract data `state'. */
3430 /* Maximal length of reservations in cycles (>= 1). */
3431 static int max_cycles_num;
3433 /* Number of set elements (see type set_el_t) needed for
3434 representation of one cycle reservation. It is depended on units
3435 number. */
3436 static int els_in_cycle_reserv;
3438 /* Number of set elements (see type set_el_t) needed for
3439 representation of maximal length reservation. Deterministic
3440 reservation is stored as set (bit string) of length equal to the
3441 variable value * number of bits in set_el_t. */
3442 static int els_in_reservs;
3444 /* Array of pointers to unit declarations. */
3445 static unit_decl_t *units_array;
3447 /* Temporary reservation of maximal length. */
3448 static reserv_sets_t temp_reserv;
3450 /* The state table itself is represented by the following variable. */
3451 static htab_t state_table;
3453 /* Linked list of free 'state' structures to be recycled. The
3454 next_equiv_class_state pointer is borrowed for a free list. */
3455 static state_t first_free_state;
3457 static int curr_unique_state_num;
3459 #ifndef NDEBUG
3460 /* The following variables is maximal number of allocated nodes
3461 `state'. */
3462 static int allocated_states_num = 0;
3463 #endif
3465 /* Allocate new reservation set. */
3466 static reserv_sets_t
3467 alloc_empty_reserv_sets (void)
3469 reserv_sets_t result;
3471 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3472 result = (reserv_sets_t) obstack_base (&irp);
3473 obstack_finish (&irp);
3474 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3475 return result;
3478 /* Hash value of reservation set. */
3479 static unsigned
3480 reserv_sets_hash_value (reserv_sets_t reservs)
3482 set_el_t hash_value;
3483 unsigned result;
3484 int reservs_num, i;
3485 set_el_t *reserv_ptr;
3487 hash_value = 0;
3488 reservs_num = els_in_reservs;
3489 reserv_ptr = reservs;
3490 i = 0;
3491 while (reservs_num != 0)
3493 reservs_num--;
3494 hash_value += ((*reserv_ptr >> i)
3495 | (*reserv_ptr << (((sizeof (set_el_t) * CHAR_BIT) - 1) & -i)));
3496 i++;
3497 if (i == sizeof (set_el_t) * CHAR_BIT)
3498 i = 0;
3499 reserv_ptr++;
3501 if (sizeof (set_el_t) <= sizeof (unsigned))
3502 return hash_value;
3503 result = 0;
3504 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3506 result += (unsigned) hash_value;
3507 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3509 return result;
3512 /* Comparison of given reservation sets. */
3513 static int
3514 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3516 int reservs_num;
3517 const set_el_t *reserv_ptr_1;
3518 const set_el_t *reserv_ptr_2;
3520 gcc_assert (reservs_1 && reservs_2);
3521 reservs_num = els_in_reservs;
3522 reserv_ptr_1 = reservs_1;
3523 reserv_ptr_2 = reservs_2;
3524 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3526 reservs_num--;
3527 reserv_ptr_1++;
3528 reserv_ptr_2++;
3530 if (reservs_num == 0)
3531 return 0;
3532 else if (*reserv_ptr_1 < *reserv_ptr_2)
3533 return -1;
3534 else
3535 return 1;
3538 /* The function checks equality of the reservation sets. */
3539 static int
3540 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3542 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3545 /* Set up in the reservation set that unit with UNIT_NUM is used on
3546 CYCLE_NUM. */
3547 static void
3548 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3550 gcc_assert (cycle_num < max_cycles_num);
3551 bitmap_set_bit (reservs, cycle_num * els_in_cycle_reserv
3552 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3555 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3556 used on CYCLE_NUM. */
3557 static int
3558 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3560 gcc_assert (cycle_num < max_cycles_num);
3561 return bitmap_bit_p (reservs, cycle_num * els_in_cycle_reserv
3562 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3565 /* The function checks that the reservation sets are intersected,
3566 i.e. there is a unit reservation on a cycle in both reservation
3567 sets. */
3568 static int
3569 reserv_sets_are_intersected (reserv_sets_t operand_1,
3570 reserv_sets_t operand_2)
3572 set_el_t *el_ptr_1;
3573 set_el_t *el_ptr_2;
3574 set_el_t *cycle_ptr_1;
3575 set_el_t *cycle_ptr_2;
3577 gcc_assert (operand_1 && operand_2);
3578 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3579 el_ptr_1 < operand_1 + els_in_reservs;
3580 el_ptr_1++, el_ptr_2++)
3581 if (*el_ptr_1 & *el_ptr_2)
3582 return 1;
3583 reserv_sets_or (temp_reserv, operand_1, operand_2);
3584 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3585 cycle_ptr_1 < operand_1 + els_in_reservs;
3586 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3588 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3589 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3590 el_ptr_1++, el_ptr_2++)
3591 if (*el_ptr_1 & *el_ptr_2)
3592 return 1;
3593 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3594 return 1;
3595 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3596 - operand_2),
3597 cycle_ptr_2, TRUE))
3598 return 1;
3599 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3600 return 1;
3601 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3602 cycle_ptr_2, TRUE))
3603 return 1;
3605 return 0;
3608 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3609 cpu cycle. The remaining bits of OPERAND (representing the last
3610 cycle unit reservations) are not changed. */
3611 static void
3612 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3614 int i;
3616 gcc_assert (result && operand && result != operand);
3617 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3618 result [i - els_in_cycle_reserv] = operand [i];
3621 /* OR of the reservation sets. */
3622 static void
3623 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3624 reserv_sets_t operand_2)
3626 set_el_t *el_ptr_1;
3627 set_el_t *el_ptr_2;
3628 set_el_t *result_set_el_ptr;
3630 gcc_assert (result && operand_1 && operand_2);
3631 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3632 el_ptr_1 < operand_1 + els_in_reservs;
3633 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3634 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3637 /* AND of the reservation sets. */
3638 static void
3639 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3640 reserv_sets_t operand_2)
3642 set_el_t *el_ptr_1;
3643 set_el_t *el_ptr_2;
3644 set_el_t *result_set_el_ptr;
3646 gcc_assert (result && operand_1 && operand_2);
3647 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3648 el_ptr_1 < operand_1 + els_in_reservs;
3649 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3650 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3653 /* The function outputs string representation of units reservation on
3654 cycle START_CYCLE in the reservation set. The function uses repeat
3655 construction if REPETITION_NUM > 1. */
3656 static void
3657 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3658 int repetition_num)
3660 int unit_num;
3661 int reserved_units_num;
3663 reserved_units_num = 0;
3664 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3665 if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3666 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3667 reserved_units_num++;
3668 gcc_assert (repetition_num > 0);
3669 if (repetition_num != 1 && reserved_units_num > 1)
3670 fprintf (f, "(");
3671 reserved_units_num = 0;
3672 for (unit_num = 0;
3673 unit_num < description->units_num;
3674 unit_num++)
3675 if (bitmap_bit_p (reservs, start_cycle * els_in_cycle_reserv
3676 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3678 if (reserved_units_num != 0)
3679 fprintf (f, "+");
3680 reserved_units_num++;
3681 fprintf (f, "%s", units_array [unit_num]->name);
3683 if (reserved_units_num == 0)
3684 fprintf (f, NOTHING_NAME);
3685 gcc_assert (repetition_num > 0);
3686 if (repetition_num != 1 && reserved_units_num > 1)
3687 fprintf (f, ")");
3688 if (repetition_num != 1)
3689 fprintf (f, "*%d", repetition_num);
3692 /* The function outputs string representation of units reservation in
3693 the reservation set. */
3694 static void
3695 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3697 int start_cycle = 0;
3698 int cycle;
3699 int repetition_num;
3701 repetition_num = 0;
3702 for (cycle = 0; cycle < max_cycles_num; cycle++)
3703 if (repetition_num == 0)
3705 repetition_num++;
3706 start_cycle = cycle;
3708 else if (memcmp
3709 ((char *) reservs + start_cycle * els_in_cycle_reserv
3710 * sizeof (set_el_t),
3711 (char *) reservs + cycle * els_in_cycle_reserv
3712 * sizeof (set_el_t),
3713 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3714 repetition_num++;
3715 else
3717 if (start_cycle != 0)
3718 fprintf (f, ", ");
3719 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3720 repetition_num = 1;
3721 start_cycle = cycle;
3723 if (start_cycle < max_cycles_num)
3725 if (start_cycle != 0)
3726 fprintf (f, ", ");
3727 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3731 /* The following function returns free node state for AUTOMATON. It
3732 may be new allocated node or node freed earlier. The function also
3733 allocates reservation set if WITH_RESERVS has nonzero value. */
3734 static state_t
3735 get_free_state (int with_reservs, automaton_t automaton)
3737 state_t result;
3739 gcc_assert (max_cycles_num > 0 && automaton);
3740 if (first_free_state)
3742 result = first_free_state;
3743 first_free_state = result->next_equiv_class_state;
3745 result->next_equiv_class_state = NULL;
3746 result->automaton = automaton;
3747 result->first_out_arc = NULL;
3748 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3749 result->it_was_placed_in_stack_for_DFA_forming = 0;
3750 result->component_states = NULL;
3752 else
3754 #ifndef NDEBUG
3755 allocated_states_num++;
3756 #endif
3757 result = XCREATENODE (struct state);
3758 result->automaton = automaton;
3759 result->first_out_arc = NULL;
3760 result->unique_num = curr_unique_state_num;
3761 curr_unique_state_num++;
3763 if (with_reservs)
3765 if (result->reservs == NULL)
3766 result->reservs = alloc_empty_reserv_sets ();
3767 else
3768 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3770 return result;
3773 /* The function frees node STATE. */
3774 static void
3775 free_state (state_t state)
3777 free_alt_states (state->component_states);
3778 state->next_equiv_class_state = first_free_state;
3779 first_free_state = state;
3782 /* Hash value of STATE. If STATE represents deterministic state it is
3783 simply hash value of the corresponding reservation set. Otherwise
3784 it is formed from hash values of the component deterministic
3785 states. One more key is order number of state automaton. */
3786 static hashval_t
3787 state_hash (const void *state)
3789 unsigned int hash_value;
3790 alt_state_t alt_state;
3792 if (((const_state_t) state)->component_states == NULL)
3793 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3794 else
3796 hash_value = 0;
3797 for (alt_state = ((const_state_t) state)->component_states;
3798 alt_state != NULL;
3799 alt_state = alt_state->next_sorted_alt_state)
3800 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3801 | (hash_value << CHAR_BIT))
3802 + alt_state->state->unique_num);
3804 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3805 | (hash_value << CHAR_BIT))
3806 + ((const_state_t) state)->automaton->automaton_order_num);
3807 return hash_value;
3810 /* Return nonzero value if the states are the same. */
3811 static int
3812 state_eq_p (const void *state_1, const void *state_2)
3814 alt_state_t alt_state_1;
3815 alt_state_t alt_state_2;
3817 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3818 return 0;
3819 else if (((const_state_t) state_1)->component_states == NULL
3820 && ((const_state_t) state_2)->component_states == NULL)
3821 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3822 ((const_state_t) state_2)->reservs);
3823 else if (((const_state_t) state_1)->component_states != NULL
3824 && ((const_state_t) state_2)->component_states != NULL)
3826 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3827 alt_state_2 = ((const_state_t) state_2)->component_states;
3828 alt_state_1 != NULL && alt_state_2 != NULL;
3829 alt_state_1 = alt_state_1->next_sorted_alt_state,
3830 alt_state_2 = alt_state_2->next_sorted_alt_state)
3831 /* All state in the list must be already in the hash table.
3832 Also the lists must be sorted. */
3833 if (alt_state_1->state != alt_state_2->state)
3834 return 0;
3835 return alt_state_1 == alt_state_2;
3837 else
3838 return 0;
3841 /* Insert STATE into the state table. */
3842 static state_t
3843 insert_state (state_t state)
3845 void **entry_ptr;
3847 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3848 if (*entry_ptr == NULL)
3849 *entry_ptr = (void *) state;
3850 return (state_t) *entry_ptr;
3853 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3854 deterministic STATE. */
3855 static void
3856 set_state_reserv (state_t state, int cycle_num, int unit_num)
3858 set_unit_reserv (state->reservs, cycle_num, unit_num);
3861 /* Return nonzero value if the deterministic states contains a
3862 reservation of the same cpu unit on the same cpu cycle. */
3863 static int
3864 intersected_state_reservs_p (state_t state1, state_t state2)
3866 gcc_assert (state1->automaton == state2->automaton);
3867 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3870 /* Return deterministic state (inserted into the table) which
3871 representing the automaton state which is union of reservations of
3872 the deterministic states masked by RESERVS. */
3873 static state_t
3874 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3876 state_t result;
3877 state_t state_in_table;
3879 gcc_assert (state1->automaton == state2->automaton);
3880 result = get_free_state (1, state1->automaton);
3881 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3882 reserv_sets_and (result->reservs, result->reservs, reservs);
3883 state_in_table = insert_state (result);
3884 if (result != state_in_table)
3886 free_state (result);
3887 result = state_in_table;
3889 return result;
3892 /* Return deterministic state (inserted into the table) which
3893 represent the automaton state is obtained from deterministic STATE
3894 by advancing cpu cycle and masking by RESERVS. */
3895 static state_t
3896 state_shift (state_t state, reserv_sets_t reservs)
3898 state_t result;
3899 state_t state_in_table;
3901 result = get_free_state (1, state->automaton);
3902 reserv_sets_shift (result->reservs, state->reservs);
3903 reserv_sets_and (result->reservs, result->reservs, reservs);
3904 state_in_table = insert_state (result);
3905 if (result != state_in_table)
3907 free_state (result);
3908 result = state_in_table;
3910 return result;
3913 /* Initialization of the abstract data. */
3914 static void
3915 initiate_states (void)
3917 decl_t decl;
3918 int i;
3920 if (description->units_num)
3921 units_array = XNEWVEC (unit_decl_t, description->units_num);
3922 else
3923 units_array = 0;
3925 for (i = 0; i < description->decls_num; i++)
3927 decl = description->decls [i];
3928 if (decl->mode == dm_unit)
3929 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3931 max_cycles_num = description->max_insn_reserv_cycles;
3932 els_in_cycle_reserv
3933 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3934 / (sizeof (set_el_t) * CHAR_BIT));
3935 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3936 curr_unique_state_num = 0;
3937 initiate_alt_states ();
3938 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3939 temp_reserv = alloc_empty_reserv_sets ();
3942 /* Finishing work with the abstract data. */
3943 static void
3944 finish_states (void)
3946 free (units_array);
3947 units_array = 0;
3948 htab_delete (state_table);
3949 first_free_state = NULL;
3950 finish_alt_states ();
3955 /* Abstract data `arcs'. */
3957 /* List of free arcs. */
3958 static arc_t first_free_arc;
3960 #ifndef NDEBUG
3961 /* The following variables is maximal number of allocated nodes
3962 `arc'. */
3963 static int allocated_arcs_num = 0;
3964 #endif
3966 /* The function frees node ARC. */
3967 static void
3968 free_arc (arc_t arc)
3970 arc->next_out_arc = first_free_arc;
3971 first_free_arc = arc;
3974 /* The function removes and frees ARC staring from FROM_STATE. */
3975 static void
3976 remove_arc (state_t from_state, arc_t arc)
3978 arc_t prev_arc;
3979 arc_t curr_arc;
3981 gcc_assert (arc);
3982 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3983 curr_arc != NULL;
3984 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3985 if (curr_arc == arc)
3986 break;
3987 gcc_assert (curr_arc);
3988 if (prev_arc == NULL)
3989 from_state->first_out_arc = arc->next_out_arc;
3990 else
3991 prev_arc->next_out_arc = arc->next_out_arc;
3992 from_state->num_out_arcs--;
3993 free_arc (arc);
3996 /* The functions returns arc with given characteristics (or NULL if
3997 the arc does not exist). */
3998 static arc_t
3999 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4001 arc_t arc;
4003 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4004 if (arc->insn == insn
4005 && (arc->to_state == to_state
4006 || (collapse_flag
4007 /* Any arc is good enough for a collapse-ndfa transition. */
4008 && (insn->insn_reserv_decl
4009 == DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
4010 return arc;
4011 return NULL;
4014 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4015 unless such an arc already exists. */
4016 static void
4017 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
4019 arc_t new_arc;
4021 new_arc = find_arc (from_state, to_state, ainsn);
4022 if (new_arc != NULL)
4023 return;
4024 if (first_free_arc == NULL)
4026 #ifndef NDEBUG
4027 allocated_arcs_num++;
4028 #endif
4029 new_arc = XCREATENODE (struct arc);
4030 new_arc->to_state = NULL;
4031 new_arc->insn = NULL;
4032 new_arc->next_out_arc = NULL;
4034 else
4036 new_arc = first_free_arc;
4037 first_free_arc = first_free_arc->next_out_arc;
4039 new_arc->to_state = to_state;
4040 new_arc->insn = ainsn;
4041 ainsn->arc_exists_p = 1;
4042 new_arc->next_out_arc = from_state->first_out_arc;
4043 from_state->first_out_arc = new_arc;
4044 from_state->num_out_arcs++;
4045 new_arc->next_arc_marked_by_insn = NULL;
4048 /* The function returns the first arc starting from STATE. */
4049 static arc_t
4050 first_out_arc (const_state_t state)
4052 return state->first_out_arc;
4055 /* The function returns next out arc after ARC. */
4056 static arc_t
4057 next_out_arc (arc_t arc)
4059 return arc->next_out_arc;
4062 /* Initialization of the abstract data. */
4063 static void
4064 initiate_arcs (void)
4066 first_free_arc = NULL;
4069 /* Finishing work with the abstract data. */
4070 static void
4071 finish_arcs (void)
4077 /* Abstract data `automata lists'. */
4079 /* List of free states. */
4080 static automata_list_el_t first_free_automata_list_el;
4082 /* The list being formed. */
4083 static automata_list_el_t current_automata_list;
4085 /* Hash table of automata lists. */
4086 static htab_t automata_list_table;
4088 /* The following function returns free automata list el. It may be
4089 new allocated node or node freed earlier. */
4090 static automata_list_el_t
4091 get_free_automata_list_el (void)
4093 automata_list_el_t result;
4095 if (first_free_automata_list_el != NULL)
4097 result = first_free_automata_list_el;
4098 first_free_automata_list_el
4099 = first_free_automata_list_el->next_automata_list_el;
4101 else
4102 result = XCREATENODE (struct automata_list_el);
4103 result->automaton = NULL;
4104 result->next_automata_list_el = NULL;
4105 return result;
4108 /* The function frees node AUTOMATA_LIST_EL. */
4109 static void
4110 free_automata_list_el (automata_list_el_t automata_list_el)
4112 if (automata_list_el == NULL)
4113 return;
4114 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4115 first_free_automata_list_el = automata_list_el;
4118 /* The function frees list AUTOMATA_LIST. */
4119 static void
4120 free_automata_list (automata_list_el_t automata_list)
4122 automata_list_el_t curr_automata_list_el;
4123 automata_list_el_t next_automata_list_el;
4125 for (curr_automata_list_el = automata_list;
4126 curr_automata_list_el != NULL;
4127 curr_automata_list_el = next_automata_list_el)
4129 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4130 free_automata_list_el (curr_automata_list_el);
4134 /* Hash value of AUTOMATA_LIST. */
4135 static hashval_t
4136 automata_list_hash (const void *automata_list)
4138 unsigned int hash_value;
4139 const_automata_list_el_t curr_automata_list_el;
4141 hash_value = 0;
4142 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4143 curr_automata_list_el != NULL;
4144 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4145 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4146 | (hash_value << CHAR_BIT))
4147 + curr_automata_list_el->automaton->automaton_order_num);
4148 return hash_value;
4151 /* Return nonzero value if the automata_lists are the same. */
4152 static int
4153 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4155 const_automata_list_el_t automata_list_el_1;
4156 const_automata_list_el_t automata_list_el_2;
4158 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4159 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4160 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4161 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4162 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4163 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4164 return 0;
4165 return automata_list_el_1 == automata_list_el_2;
4168 /* Initialization of the abstract data. */
4169 static void
4170 initiate_automata_lists (void)
4172 first_free_automata_list_el = NULL;
4173 automata_list_table = htab_create (1500, automata_list_hash,
4174 automata_list_eq_p, (htab_del) 0);
4177 /* The following function starts new automata list and makes it the
4178 current one. */
4179 static void
4180 automata_list_start (void)
4182 current_automata_list = NULL;
4185 /* The following function adds AUTOMATON to the current list. */
4186 static void
4187 automata_list_add (automaton_t automaton)
4189 automata_list_el_t el;
4191 el = get_free_automata_list_el ();
4192 el->automaton = automaton;
4193 el->next_automata_list_el = current_automata_list;
4194 current_automata_list = el;
4197 /* The following function finishes forming the current list, inserts
4198 it into the table and returns it. */
4199 static automata_list_el_t
4200 automata_list_finish (void)
4202 void **entry_ptr;
4204 if (current_automata_list == NULL)
4205 return NULL;
4206 entry_ptr = htab_find_slot (automata_list_table,
4207 (void *) current_automata_list, INSERT);
4208 if (*entry_ptr == NULL)
4209 *entry_ptr = (void *) current_automata_list;
4210 else
4211 free_automata_list (current_automata_list);
4212 current_automata_list = NULL;
4213 return (automata_list_el_t) *entry_ptr;
4216 /* Finishing work with the abstract data. */
4217 static void
4218 finish_automata_lists (void)
4220 htab_delete (automata_list_table);
4225 /* The page contains abstract data for work with exclusion sets (see
4226 exclusion_set in file rtl.def). */
4228 /* The following variable refers to an exclusion set returned by
4229 get_excl_set. This is bit string of length equal to cpu units
4230 number. If exclusion set for given unit contains 1 for a unit,
4231 then simultaneous reservation of the units is prohibited. */
4232 static reserv_sets_t excl_set;
4234 /* The array contains exclusion sets for each unit. */
4235 static reserv_sets_t *unit_excl_set_table;
4237 /* The following function forms the array containing exclusion sets
4238 for each unit. */
4239 static void
4240 initiate_excl_sets (void)
4242 decl_t decl;
4243 reserv_sets_t unit_excl_set;
4244 unit_set_el_t el;
4245 int i;
4247 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4248 excl_set = (reserv_sets_t) obstack_base (&irp);
4249 obstack_finish (&irp);
4250 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4251 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4252 obstack_finish (&irp);
4253 /* Evaluate unit exclusion sets. */
4254 for (i = 0; i < description->decls_num; i++)
4256 decl = description->decls [i];
4257 if (decl->mode == dm_unit)
4259 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4260 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4261 obstack_finish (&irp);
4262 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4263 for (el = DECL_UNIT (decl)->excl_list;
4264 el != NULL;
4265 el = el->next_unit_set_el)
4267 bitmap_set_bit (unit_excl_set, el->unit_decl->unit_num);
4268 el->unit_decl->in_set_p = TRUE;
4270 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4275 /* The function sets up and return EXCL_SET which is union of
4276 exclusion sets for each unit in IN_SET. */
4277 static reserv_sets_t
4278 get_excl_set (reserv_sets_t in_set)
4280 int el;
4281 unsigned int i;
4282 int start_unit_num;
4283 int unit_num;
4285 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4286 for (el = 0; el < els_in_cycle_reserv; el++)
4287 if (in_set[el])
4288 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4289 if ((in_set[el] >> i) & 1)
4291 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4292 if (start_unit_num >= description->units_num)
4293 return excl_set;
4294 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4296 excl_set [unit_num]
4297 |= unit_excl_set_table [start_unit_num] [unit_num];
4300 return excl_set;
4305 /* The page contains abstract data for work with presence/absence
4306 pattern sets (see presence_set/absence_set in file rtl.def). */
4308 /* The following arrays contain correspondingly presence, final
4309 presence, absence, and final absence patterns for each unit. */
4310 static pattern_reserv_t *unit_presence_set_table;
4311 static pattern_reserv_t *unit_final_presence_set_table;
4312 static pattern_reserv_t *unit_absence_set_table;
4313 static pattern_reserv_t *unit_final_absence_set_table;
4315 /* The following function forms list of reservation sets for given
4316 PATTERN_LIST. */
4317 static pattern_reserv_t
4318 form_reserv_sets_list (pattern_set_el_t pattern_list)
4320 pattern_set_el_t el;
4321 pattern_reserv_t first, curr, prev;
4322 int i;
4324 prev = first = NULL;
4325 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4327 curr = XCREATENODE (struct pattern_reserv);
4328 curr->reserv = alloc_empty_reserv_sets ();
4329 curr->next_pattern_reserv = NULL;
4330 for (i = 0; i < el->units_num; i++)
4332 bitmap_set_bit (curr->reserv, el->unit_decls [i]->unit_num);
4333 el->unit_decls [i]->in_set_p = TRUE;
4335 if (prev != NULL)
4336 prev->next_pattern_reserv = curr;
4337 else
4338 first = curr;
4339 prev = curr;
4341 return first;
4344 /* The following function forms the array containing presence and
4345 absence pattern sets for each unit. */
4346 static void
4347 initiate_presence_absence_pattern_sets (void)
4349 decl_t decl;
4350 int i;
4352 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4353 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4354 obstack_finish (&irp);
4355 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4356 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4357 obstack_finish (&irp);
4358 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4359 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4360 obstack_finish (&irp);
4361 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4362 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4363 obstack_finish (&irp);
4364 /* Evaluate unit presence/absence sets. */
4365 for (i = 0; i < description->decls_num; i++)
4367 decl = description->decls [i];
4368 if (decl->mode == dm_unit)
4370 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4371 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4372 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4373 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4374 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4375 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4376 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4377 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4382 /* The function checks that CHECKED_SET satisfies all presence pattern
4383 sets for units in ORIGINAL_SET. The function returns TRUE if it
4384 is ok. */
4385 static int
4386 check_presence_pattern_sets (reserv_sets_t checked_set,
4387 reserv_sets_t original_set,
4388 int final_p)
4390 int el;
4391 unsigned int i;
4392 int start_unit_num;
4393 int unit_num;
4394 int presence_p;
4395 pattern_reserv_t pat_reserv;
4397 for (el = 0; el < els_in_cycle_reserv; el++)
4398 if (original_set[el])
4399 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4400 if ((original_set[el] >> i) & 1)
4402 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4403 if (start_unit_num >= description->units_num)
4404 break;
4405 if ((final_p
4406 && unit_final_presence_set_table [start_unit_num] == NULL)
4407 || (!final_p
4408 && unit_presence_set_table [start_unit_num] == NULL))
4409 continue;
4410 presence_p = FALSE;
4411 for (pat_reserv = (final_p
4412 ? unit_final_presence_set_table [start_unit_num]
4413 : unit_presence_set_table [start_unit_num]);
4414 pat_reserv != NULL;
4415 pat_reserv = pat_reserv->next_pattern_reserv)
4417 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4418 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4419 != pat_reserv->reserv [unit_num])
4420 break;
4421 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4423 if (!presence_p)
4424 return FALSE;
4426 return TRUE;
4429 /* The function checks that CHECKED_SET satisfies all absence pattern
4430 sets for units in ORIGINAL_SET. The function returns TRUE if it
4431 is ok. */
4432 static int
4433 check_absence_pattern_sets (reserv_sets_t checked_set,
4434 reserv_sets_t original_set,
4435 int final_p)
4437 int el;
4438 unsigned int i;
4439 int start_unit_num;
4440 int unit_num;
4441 pattern_reserv_t pat_reserv;
4443 for (el = 0; el < els_in_cycle_reserv; el++)
4444 if (original_set[el])
4445 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4446 if ((original_set[el] >> i) & 1)
4448 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4449 if (start_unit_num >= description->units_num)
4450 break;
4451 for (pat_reserv = (final_p
4452 ? unit_final_absence_set_table [start_unit_num]
4453 : unit_absence_set_table [start_unit_num]);
4454 pat_reserv != NULL;
4455 pat_reserv = pat_reserv->next_pattern_reserv)
4457 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4458 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4459 != pat_reserv->reserv [unit_num]
4460 && pat_reserv->reserv [unit_num])
4461 break;
4462 if (unit_num >= els_in_cycle_reserv)
4463 return FALSE;
4466 return TRUE;
4471 /* This page contains code for transformation of original reservations
4472 described in .md file. The main goal of transformations is
4473 simplifying reservation and lifting up all `|' on the top of IR
4474 reservation representation. */
4477 /* The following function makes copy of IR representation of
4478 reservation. The function also substitutes all reservations
4479 defined by define_reservation by corresponding value during making
4480 the copy. */
4481 static regexp_t
4482 copy_insn_regexp (regexp_t regexp)
4484 regexp_t result;
4485 int i;
4487 switch (regexp->mode)
4489 case rm_reserv:
4490 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4491 break;
4493 case rm_unit:
4494 result = XCOPYNODE (struct regexp, regexp);
4495 break;
4497 case rm_repeat:
4498 result = XCOPYNODE (struct regexp, regexp);
4499 REGEXP_REPEAT (result)->regexp
4500 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4501 break;
4503 case rm_sequence:
4504 result = XCOPYNODEVAR (struct regexp, regexp,
4505 sizeof (struct regexp) + sizeof (regexp_t)
4506 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4507 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4508 REGEXP_SEQUENCE (result)->regexps [i]
4509 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4510 break;
4512 case rm_allof:
4513 result = XCOPYNODEVAR (struct regexp, regexp,
4514 sizeof (struct regexp) + sizeof (regexp_t)
4515 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4516 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4517 REGEXP_ALLOF (result)->regexps [i]
4518 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4519 break;
4521 case rm_oneof:
4522 result = XCOPYNODEVAR (struct regexp, regexp,
4523 sizeof (struct regexp) + sizeof (regexp_t)
4524 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4525 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4526 REGEXP_ONEOF (result)->regexps [i]
4527 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4528 break;
4530 case rm_nothing:
4531 result = XCOPYNODE (struct regexp, regexp);
4532 break;
4534 default:
4535 gcc_unreachable ();
4537 return result;
4540 /* The following variable is set up 1 if a transformation has been
4541 applied. */
4542 static int regexp_transformed_p;
4544 /* The function makes transformation
4545 A*N -> A, A, ... */
4546 static regexp_t
4547 transform_1 (regexp_t regexp)
4549 int i;
4550 int repeat_num;
4551 regexp_t operand;
4552 pos_t pos;
4554 if (regexp->mode == rm_repeat)
4556 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4557 gcc_assert (repeat_num > 1);
4558 operand = REGEXP_REPEAT (regexp)->regexp;
4559 pos = regexp->mode;
4560 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4561 + sizeof (regexp_t) * (repeat_num - 1));
4562 regexp->mode = rm_sequence;
4563 regexp->pos = pos;
4564 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4565 for (i = 0; i < repeat_num; i++)
4566 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4567 regexp_transformed_p = 1;
4569 return regexp;
4572 /* The function makes transformations
4573 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4574 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4575 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4576 static regexp_t
4577 transform_2 (regexp_t regexp)
4579 if (regexp->mode == rm_sequence)
4581 regexp_t sequence = NULL;
4582 regexp_t result;
4583 int sequence_index = 0;
4584 int i, j;
4586 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4587 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4589 sequence_index = i;
4590 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4591 break;
4593 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4595 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4596 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4597 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4598 + sizeof (regexp_t)
4599 * (REGEXP_SEQUENCE (regexp)->regexps_num
4600 + REGEXP_SEQUENCE (sequence)->regexps_num
4601 - 2));
4602 result->mode = rm_sequence;
4603 result->pos = regexp->pos;
4604 REGEXP_SEQUENCE (result)->regexps_num
4605 = (REGEXP_SEQUENCE (regexp)->regexps_num
4606 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4607 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4608 if (i < sequence_index)
4609 REGEXP_SEQUENCE (result)->regexps [i]
4610 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4611 else if (i > sequence_index)
4612 REGEXP_SEQUENCE (result)->regexps
4613 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4614 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4615 else
4616 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4617 REGEXP_SEQUENCE (result)->regexps [i + j]
4618 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4619 regexp_transformed_p = 1;
4620 regexp = result;
4623 else if (regexp->mode == rm_allof)
4625 regexp_t allof = NULL;
4626 regexp_t result;
4627 int allof_index = 0;
4628 int i, j;
4630 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4631 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4633 allof_index = i;
4634 allof = REGEXP_ALLOF (regexp)->regexps [i];
4635 break;
4637 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4639 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4640 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4641 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4642 + sizeof (regexp_t)
4643 * (REGEXP_ALLOF (regexp)->regexps_num
4644 + REGEXP_ALLOF (allof)->regexps_num - 2));
4645 result->mode = rm_allof;
4646 result->pos = regexp->pos;
4647 REGEXP_ALLOF (result)->regexps_num
4648 = (REGEXP_ALLOF (regexp)->regexps_num
4649 + REGEXP_ALLOF (allof)->regexps_num - 1);
4650 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4651 if (i < allof_index)
4652 REGEXP_ALLOF (result)->regexps [i]
4653 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4654 else if (i > allof_index)
4655 REGEXP_ALLOF (result)->regexps
4656 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4657 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4658 else
4659 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4660 REGEXP_ALLOF (result)->regexps [i + j]
4661 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4662 regexp_transformed_p = 1;
4663 regexp = result;
4666 else if (regexp->mode == rm_oneof)
4668 regexp_t oneof = NULL;
4669 regexp_t result;
4670 int oneof_index = 0;
4671 int i, j;
4673 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4674 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4676 oneof_index = i;
4677 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4678 break;
4680 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4682 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4683 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4684 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4685 + sizeof (regexp_t)
4686 * (REGEXP_ONEOF (regexp)->regexps_num
4687 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4688 result->mode = rm_oneof;
4689 result->pos = regexp->pos;
4690 REGEXP_ONEOF (result)->regexps_num
4691 = (REGEXP_ONEOF (regexp)->regexps_num
4692 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4693 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4694 if (i < oneof_index)
4695 REGEXP_ONEOF (result)->regexps [i]
4696 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4697 else if (i > oneof_index)
4698 REGEXP_ONEOF (result)->regexps
4699 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4700 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4701 else
4702 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4703 REGEXP_ONEOF (result)->regexps [i + j]
4704 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4705 regexp_transformed_p = 1;
4706 regexp = result;
4709 return regexp;
4712 /* The function makes transformations
4713 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4714 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4715 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4716 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4717 static regexp_t
4718 transform_3 (regexp_t regexp)
4720 if (regexp->mode == rm_sequence)
4722 regexp_t oneof = NULL;
4723 int oneof_index = 0;
4724 regexp_t result;
4725 regexp_t sequence;
4726 int i, j;
4728 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4729 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4731 oneof_index = i;
4732 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4733 break;
4735 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4737 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4738 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4739 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4740 + sizeof (regexp_t)
4741 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4742 result->mode = rm_oneof;
4743 result->pos = regexp->pos;
4744 REGEXP_ONEOF (result)->regexps_num
4745 = REGEXP_ONEOF (oneof)->regexps_num;
4746 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4748 sequence
4749 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4750 + sizeof (regexp_t)
4751 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4752 sequence->mode = rm_sequence;
4753 sequence->pos = regexp->pos;
4754 REGEXP_SEQUENCE (sequence)->regexps_num
4755 = REGEXP_SEQUENCE (regexp)->regexps_num;
4756 REGEXP_ONEOF (result)->regexps [i] = sequence;
4757 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4758 if (j != oneof_index)
4759 REGEXP_SEQUENCE (sequence)->regexps [j]
4760 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4761 else
4762 REGEXP_SEQUENCE (sequence)->regexps [j]
4763 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4765 regexp_transformed_p = 1;
4766 regexp = result;
4769 else if (regexp->mode == rm_allof)
4771 regexp_t oneof = NULL;
4772 regexp_t seq;
4773 int oneof_index = 0;
4774 int max_seq_length, allof_length;
4775 regexp_t result;
4776 regexp_t allof = NULL;
4777 regexp_t allof_op = NULL;
4778 int i, j;
4780 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4781 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4783 oneof_index = i;
4784 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4785 break;
4787 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4789 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4790 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4791 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4792 + sizeof (regexp_t)
4793 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4794 result->mode = rm_oneof;
4795 result->pos = regexp->pos;
4796 REGEXP_ONEOF (result)->regexps_num
4797 = REGEXP_ONEOF (oneof)->regexps_num;
4798 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4800 allof
4801 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4802 + sizeof (regexp_t)
4803 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4804 allof->mode = rm_allof;
4805 allof->pos = regexp->pos;
4806 REGEXP_ALLOF (allof)->regexps_num
4807 = REGEXP_ALLOF (regexp)->regexps_num;
4808 REGEXP_ONEOF (result)->regexps [i] = allof;
4809 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4810 if (j != oneof_index)
4811 REGEXP_ALLOF (allof)->regexps [j]
4812 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4813 else
4814 REGEXP_ALLOF (allof)->regexps [j]
4815 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4817 regexp_transformed_p = 1;
4818 regexp = result;
4820 max_seq_length = 0;
4821 if (regexp->mode == rm_allof)
4822 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4824 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4826 case rm_sequence:
4827 seq = REGEXP_ALLOF (regexp)->regexps [i];
4828 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4829 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4830 break;
4832 case rm_unit:
4833 case rm_nothing:
4834 break;
4836 default:
4837 max_seq_length = 0;
4838 goto break_for;
4841 break_for:
4842 if (max_seq_length != 0)
4844 gcc_assert (max_seq_length != 1
4845 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4846 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4847 + sizeof (regexp_t) * (max_seq_length - 1));
4848 result->mode = rm_sequence;
4849 result->pos = regexp->pos;
4850 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4851 for (i = 0; i < max_seq_length; i++)
4853 allof_length = 0;
4854 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4855 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4857 case rm_sequence:
4858 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4859 ->regexps [j])->regexps_num))
4861 allof_op
4862 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4863 ->regexps [j])
4864 ->regexps [i]);
4865 allof_length++;
4867 break;
4868 case rm_unit:
4869 case rm_nothing:
4870 if (i == 0)
4872 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4873 allof_length++;
4875 break;
4876 default:
4877 break;
4880 if (allof_length == 1)
4881 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4882 else
4884 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4885 + sizeof (regexp_t)
4886 * (allof_length - 1));
4887 allof->mode = rm_allof;
4888 allof->pos = regexp->pos;
4889 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4890 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4891 allof_length = 0;
4892 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4893 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4894 && (i <
4895 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4896 ->regexps [j])->regexps_num)))
4898 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4899 ->regexps [j])
4900 ->regexps [i]);
4901 REGEXP_ALLOF (allof)->regexps [allof_length]
4902 = allof_op;
4903 allof_length++;
4905 else if (i == 0
4906 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4907 == rm_unit
4908 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4909 == rm_nothing)))
4911 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4912 REGEXP_ALLOF (allof)->regexps [allof_length]
4913 = allof_op;
4914 allof_length++;
4918 regexp_transformed_p = 1;
4919 regexp = result;
4922 return regexp;
4925 /* The function traverses IR of reservation and applies transformations
4926 implemented by FUNC. */
4927 static regexp_t
4928 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4930 int i;
4932 switch (regexp->mode)
4934 case rm_sequence:
4935 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4936 REGEXP_SEQUENCE (regexp)->regexps [i]
4937 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4938 func);
4939 break;
4941 case rm_allof:
4942 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4943 REGEXP_ALLOF (regexp)->regexps [i]
4944 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4945 break;
4947 case rm_oneof:
4948 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4949 REGEXP_ONEOF (regexp)->regexps [i]
4950 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4951 break;
4953 case rm_repeat:
4954 REGEXP_REPEAT (regexp)->regexp
4955 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4956 break;
4958 case rm_nothing:
4959 case rm_unit:
4960 break;
4962 default:
4963 gcc_unreachable ();
4965 return (*func) (regexp);
4968 /* The function applies all transformations for IR representation of
4969 reservation REGEXP. */
4970 static regexp_t
4971 transform_regexp (regexp_t regexp)
4973 regexp = regexp_transform_func (regexp, transform_1);
4976 regexp_transformed_p = 0;
4977 regexp = regexp_transform_func (regexp, transform_2);
4978 regexp = regexp_transform_func (regexp, transform_3);
4980 while (regexp_transformed_p);
4981 return regexp;
4984 /* The function applies all transformations for reservations of all
4985 insn declarations. */
4986 static void
4987 transform_insn_regexps (void)
4989 decl_t decl;
4990 int i;
4992 transform_time = create_ticker ();
4993 add_advance_cycle_insn_decl ();
4994 if (collapse_flag)
4995 add_collapse_ndfa_insn_decl ();
4996 if (progress_flag)
4997 fprintf (stderr, "Reservation transformation...");
4998 for (i = 0; i < description->normal_decls_num; i++)
5000 decl = description->decls [i];
5001 if (decl->mode == dm_insn_reserv)
5002 DECL_INSN_RESERV (decl)->transformed_regexp
5003 = transform_regexp (copy_insn_regexp
5004 (DECL_INSN_RESERV (decl)->regexp));
5006 if (progress_flag)
5007 fprintf (stderr, "done\n");
5008 ticker_off (&transform_time);
5013 /* The following variable value is TRUE if the first annotated message
5014 about units to automata distribution has been output. */
5015 static int annotation_message_reported_p;
5017 /* The vector contains all decls which are automata. */
5018 static vec<decl_t> automaton_decls;
5020 /* The following structure describes usage of a unit in a reservation. */
5021 struct unit_usage
5023 unit_decl_t unit_decl;
5024 /* The following forms a list of units used on the same cycle in the
5025 same alternative. The list is ordered by the correspdoning unit
5026 declarations and there is no unit declaration duplication in the
5027 list. */
5028 struct unit_usage *next;
5030 typedef struct unit_usage *unit_usage_t;
5033 /* Obstack for unit_usage structures. */
5034 static struct obstack unit_usages;
5036 /* VLA for representation of array of pointers to unit usage
5037 structures. There is an element for each combination of
5038 (alternative number, cycle). Unit usages on given cycle in
5039 alternative with given number are referred through element with
5040 index equals to the cycle * number of all alternatives in the
5041 regexp + the alternative number. */
5042 static vec<unit_usage_t> cycle_alt_unit_usages;
5044 /* The following function creates the structure unit_usage for UNIT on
5045 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5046 accessed through cycle_alt_unit_usages. */
5047 static void
5048 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5049 int alt_num)
5051 size_t length;
5052 unit_decl_t unit_decl;
5053 unit_usage_t unit_usage_ptr, curr, prev;
5054 int index;
5056 gcc_assert (regexp && regexp->mode == rm_oneof
5057 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
5058 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5060 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5061 while (cycle_alt_unit_usages.length () < length)
5062 cycle_alt_unit_usages.safe_push (NULL);
5064 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5065 prev = NULL;
5066 for (curr = cycle_alt_unit_usages[index];
5067 curr != NULL;
5068 prev = curr, curr = curr->next)
5069 if (curr->unit_decl >= unit_decl)
5070 break;
5071 if (curr != NULL && curr->unit_decl == unit_decl)
5072 return;
5073 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5074 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5075 obstack_finish (&unit_usages);
5076 unit_usage_ptr->unit_decl = unit_decl;
5077 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5078 unit_usage_ptr->next = curr;
5079 if (prev == NULL)
5080 cycle_alt_unit_usages[index] = unit_usage_ptr;
5081 else
5082 prev->next = unit_usage_ptr;
5085 /* Return true if unit UNIT_DECL is present on the LIST. */
5086 static bool
5087 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5089 while (list != NULL)
5091 if (list->unit_decl == unit_decl)
5092 return true;
5093 list = list->next;
5095 return false;
5098 /* The function returns true if reservations of alternatives ALT1 and
5099 ALT2 are equal after excluding reservations of units of
5100 EXCLUDED_AUTOMATON_DECL. */
5101 static bool
5102 equal_alternatives_p (int alt1, int alt2, int n_alts,
5103 struct automaton_decl *excluded_automaton_decl)
5105 int i;
5106 unit_usage_t list1, list2;
5108 for (i = 0;
5109 i < (int) cycle_alt_unit_usages.length ();
5110 i += n_alts)
5112 for (list1 = cycle_alt_unit_usages[i + alt1],
5113 list2 = cycle_alt_unit_usages[i + alt2];;
5114 list1 = list1->next, list2 = list2->next)
5116 while (list1 != NULL
5117 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5118 list1 = list1->next;
5119 while (list2 != NULL
5120 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5121 list2 = list2->next;
5122 if (list1 == NULL || list2 == NULL)
5124 if (list1 != list2)
5125 return false;
5126 else
5127 break;
5129 if (list1->unit_decl != list2->unit_decl)
5130 return false;
5133 return true;
5137 /* The function processes given REGEXP to find units with the wrong
5138 distribution. */
5139 static void
5140 check_regexp_units_distribution (const char *insn_reserv_name,
5141 regexp_t regexp)
5143 int i, j, k, cycle, start, n_alts, alt, alt2;
5144 bool annotation_reservation_message_reported_p;
5145 regexp_t seq, allof, unit;
5146 struct unit_usage *unit_usage_ptr;
5148 if (regexp == NULL || regexp->mode != rm_oneof)
5149 return;
5150 /* Store all unit usages in the regexp: */
5151 obstack_init (&unit_usages);
5152 cycle_alt_unit_usages.create (10);
5154 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5156 seq = REGEXP_ONEOF (regexp)->regexps [i];
5157 switch (seq->mode)
5159 case rm_sequence:
5160 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5162 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5163 switch (allof->mode)
5165 case rm_allof:
5166 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5168 unit = REGEXP_ALLOF (allof)->regexps [k];
5169 if (unit->mode == rm_unit)
5170 store_alt_unit_usage (regexp, unit, j, i);
5171 else
5172 gcc_assert (unit->mode == rm_nothing);
5174 break;
5176 case rm_unit:
5177 store_alt_unit_usage (regexp, allof, j, i);
5178 break;
5180 case rm_nothing:
5181 break;
5183 default:
5184 gcc_unreachable ();
5187 break;
5189 case rm_allof:
5190 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5192 unit = REGEXP_ALLOF (seq)->regexps [k];
5193 switch (unit->mode)
5195 case rm_unit:
5196 store_alt_unit_usage (regexp, unit, 0, i);
5197 break;
5199 case rm_nothing:
5200 break;
5202 default:
5203 gcc_unreachable ();
5206 break;
5208 case rm_unit:
5209 store_alt_unit_usage (regexp, seq, 0, i);
5210 break;
5212 case rm_nothing:
5213 break;
5215 default:
5216 gcc_unreachable ();
5219 /* Check distribution: */
5220 for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5221 for (unit_usage_ptr = cycle_alt_unit_usages[i];
5222 unit_usage_ptr != NULL;
5223 unit_usage_ptr = unit_usage_ptr->next)
5224 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5225 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5226 auto_vec<int> marked (n_alts);
5227 for (i = 0; i < n_alts; i++)
5228 marked.safe_push (0);
5229 annotation_reservation_message_reported_p = false;
5230 for (i = 0; i < (int) cycle_alt_unit_usages.length (); i++)
5232 cycle = i / n_alts;
5233 start = cycle * n_alts;
5234 for (unit_usage_ptr = cycle_alt_unit_usages[i];
5235 unit_usage_ptr != NULL;
5236 unit_usage_ptr = unit_usage_ptr->next)
5238 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5239 continue;
5240 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5241 for (alt = 0; alt < n_alts; alt++)
5242 if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5243 unit_usage_ptr->unit_decl))
5244 break;
5245 if (alt >= n_alts)
5246 continue;
5247 memset (marked.address (), 0, n_alts * sizeof (int));
5248 for (alt = 0; alt < n_alts; alt++)
5250 if (! unit_present_on_list_p (cycle_alt_unit_usages[start + alt],
5251 unit_usage_ptr->unit_decl))
5252 continue;
5253 for (j = 0;
5254 j < (int) cycle_alt_unit_usages.length ();
5255 j++)
5257 alt2 = j % n_alts;
5258 if (! unit_present_on_list_p
5259 (cycle_alt_unit_usages[start + alt2],
5260 unit_usage_ptr->unit_decl)
5261 && equal_alternatives_p (alt, alt2, n_alts,
5262 unit_usage_ptr
5263 ->unit_decl->automaton_decl))
5265 marked[alt] = 1;
5266 marked[alt2] = 1;
5270 for (alt = 0; alt < n_alts && marked[alt]; alt++)
5272 if (alt < n_alts && 0)
5274 if (! annotation_message_reported_p)
5276 fprintf (stderr, "\n");
5277 error ("The following units do not satisfy units-automata distribution rule");
5278 error ("(Unit presence on one alt and its absence on other alt\n");
5279 error (" result in different other automata reservations)");
5280 annotation_message_reported_p = TRUE;
5282 if (! annotation_reservation_message_reported_p)
5284 error ("Reserv %s:", insn_reserv_name);
5285 annotation_reservation_message_reported_p = true;
5287 error (" Unit %s, cycle %d, alt %d, another alt %d",
5288 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5292 cycle_alt_unit_usages.release ();
5293 obstack_free (&unit_usages, NULL);
5296 /* The function finds units which violates units to automata
5297 distribution rule. If the units exist, report about them. */
5298 static void
5299 check_unit_distributions_to_automata (void)
5301 decl_t decl;
5302 int i;
5304 if (progress_flag)
5305 fprintf (stderr, "Check unit distributions to automata...");
5306 automaton_decls.create (0);
5307 for (i = 0; i < description->decls_num; i++)
5309 decl = description->decls [i];
5310 if (decl->mode == dm_automaton)
5311 automaton_decls.safe_push (decl);
5313 if (automaton_decls.length () > 1)
5315 annotation_message_reported_p = FALSE;
5316 for (i = 0; i < description->decls_num; i++)
5318 decl = description->decls [i];
5319 if (decl->mode == dm_insn_reserv)
5320 check_regexp_units_distribution
5321 (DECL_INSN_RESERV (decl)->name,
5322 DECL_INSN_RESERV (decl)->transformed_regexp);
5325 automaton_decls.release ();
5326 if (progress_flag)
5327 fprintf (stderr, "done\n");
5332 /* The page contains code for building alt_states (see comments for
5333 IR) describing all possible insns reservations of an automaton. */
5335 /* Current state being formed for which the current alt_state
5336 refers. */
5337 static state_t state_being_formed;
5339 /* Current alt_state being formed. */
5340 static alt_state_t alt_state_being_formed;
5342 /* This recursive function processes `,' and units in reservation
5343 REGEXP for forming alt_states of AUTOMATON. It is believed that
5344 CURR_CYCLE is start cycle of all reservation REGEXP. */
5345 static int
5346 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5347 int curr_cycle)
5349 int i;
5351 if (regexp == NULL)
5352 return curr_cycle;
5354 switch (regexp->mode)
5356 case rm_unit:
5357 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5358 == automaton->automaton_order_num)
5359 set_state_reserv (state_being_formed, curr_cycle,
5360 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5361 return curr_cycle;
5363 case rm_sequence:
5364 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5365 curr_cycle
5366 = process_seq_for_forming_states
5367 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5368 return curr_cycle;
5370 case rm_allof:
5372 int finish_cycle = 0;
5373 int cycle;
5375 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5377 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5378 ->regexps [i],
5379 automaton, curr_cycle);
5380 if (finish_cycle < cycle)
5381 finish_cycle = cycle;
5383 return finish_cycle;
5386 case rm_nothing:
5387 return curr_cycle;
5389 default:
5390 gcc_unreachable ();
5394 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5395 inserts alt_state into the table. */
5396 static void
5397 finish_forming_alt_state (alt_state_t alt_state,
5398 automaton_t automaton ATTRIBUTE_UNUSED)
5400 state_t state_in_table;
5401 state_t corresponding_state;
5403 corresponding_state = alt_state->state;
5404 state_in_table = insert_state (corresponding_state);
5405 if (state_in_table != corresponding_state)
5407 free_state (corresponding_state);
5408 alt_state->state = state_in_table;
5412 /* The following variable value is current automaton insn for whose
5413 reservation the alt states are created. */
5414 static ainsn_t curr_ainsn;
5416 /* This recursive function processes `|' in reservation REGEXP for
5417 forming alt_states of AUTOMATON. List of the alt states should
5418 have the same order as in the description. */
5419 static void
5420 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5421 int inside_oneof_p)
5423 int i;
5425 if (regexp->mode != rm_oneof)
5427 alt_state_being_formed = get_free_alt_state ();
5428 state_being_formed = get_free_state (1, automaton);
5429 alt_state_being_formed->state = state_being_formed;
5430 /* We inserts in reverse order but we process alternatives also
5431 in reverse order. So we have the same order of alternative
5432 as in the description. */
5433 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5434 curr_ainsn->alt_states = alt_state_being_formed;
5435 (void) process_seq_for_forming_states (regexp, automaton, 0);
5436 finish_forming_alt_state (alt_state_being_formed, automaton);
5438 else
5440 gcc_assert (!inside_oneof_p);
5441 /* We processes it in reverse order to get list with the same
5442 order as in the description. See also the previous
5443 commentary. */
5444 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5445 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5446 automaton, 1);
5450 /* Create nodes alt_state for all AUTOMATON insns. */
5451 static void
5452 create_alt_states (automaton_t automaton)
5454 struct insn_reserv_decl *reserv_decl;
5456 for (curr_ainsn = automaton->ainsn_list;
5457 curr_ainsn != NULL;
5458 curr_ainsn = curr_ainsn->next_ainsn)
5460 reserv_decl = curr_ainsn->insn_reserv_decl;
5461 if (!special_decl_p (reserv_decl))
5463 curr_ainsn->alt_states = NULL;
5464 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5465 automaton, 0);
5466 curr_ainsn->sorted_alt_states
5467 = uniq_sort_alt_states (curr_ainsn->alt_states);
5474 /* The page contains major code for building DFA(s) for fast pipeline
5475 hazards recognition. */
5477 /* The function forms list of ainsns of AUTOMATON with the same
5478 reservation. */
5480 static void
5481 form_ainsn_with_same_reservs (automaton_t automaton)
5483 ainsn_t curr_ainsn;
5484 size_t i;
5485 auto_vec<ainsn_t, 150> last_insns;
5487 for (curr_ainsn = automaton->ainsn_list;
5488 curr_ainsn != NULL;
5489 curr_ainsn = curr_ainsn->next_ainsn)
5490 if (special_decl_p (curr_ainsn->insn_reserv_decl))
5492 curr_ainsn->next_same_reservs_insn = NULL;
5493 curr_ainsn->first_insn_with_same_reservs = 1;
5495 else
5497 for (i = 0; i < last_insns.length (); i++)
5498 if (alt_states_eq
5499 (curr_ainsn->sorted_alt_states,
5500 last_insns[i]->sorted_alt_states))
5501 break;
5502 curr_ainsn->next_same_reservs_insn = NULL;
5503 if (i < last_insns.length ())
5505 curr_ainsn->first_insn_with_same_reservs = 0;
5506 last_insns[i]->next_same_reservs_insn = curr_ainsn;
5507 last_insns[i] = curr_ainsn;
5509 else
5511 last_insns.safe_push (curr_ainsn);
5512 curr_ainsn->first_insn_with_same_reservs = 1;
5517 /* Forming unit reservations which can affect creating the automaton
5518 states achieved from a given state. It permits to build smaller
5519 automata in many cases. We would have the same automata after
5520 the minimization without such optimization, but the automaton
5521 right after the building could be huge. So in other words, usage
5522 of reservs_matter means some minimization during building the
5523 automaton. */
5524 static reserv_sets_t
5525 form_reservs_matter (automaton_t automaton)
5527 int cycle, unit;
5528 reserv_sets_t reservs_matter = alloc_empty_reserv_sets ();
5530 for (cycle = 0; cycle < max_cycles_num; cycle++)
5531 for (unit = 0; unit < description->units_num; unit++)
5532 if (units_array [unit]->automaton_decl
5533 == automaton->corresponding_automaton_decl
5534 && (cycle >= units_array [unit]->min_occ_cycle_num
5535 /* We can not remove queried unit from reservations. */
5536 || units_array [unit]->query_p
5537 /* We can not remove units which are used
5538 `exclusion_set', `presence_set',
5539 `final_presence_set', `absence_set', and
5540 `final_absence_set'. */
5541 || units_array [unit]->in_set_p))
5542 set_unit_reserv (reservs_matter, cycle, unit);
5543 return reservs_matter;
5546 /* The following function creates all states of nondeterministic AUTOMATON. */
5547 static void
5548 make_automaton (automaton_t automaton)
5550 ainsn_t ainsn;
5551 struct insn_reserv_decl *insn_reserv_decl;
5552 alt_state_t alt_state;
5553 state_t state;
5554 state_t start_state;
5555 state_t state2;
5556 auto_vec<state_t, 150> state_stack;
5557 int states_n;
5558 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5560 /* Create the start state (empty state). */
5561 start_state = insert_state (get_free_state (1, automaton));
5562 automaton->start_state = start_state;
5563 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5564 state_stack.safe_push (start_state);
5565 states_n = 1;
5566 while (state_stack.length () != 0)
5568 state = state_stack.pop ();
5569 for (ainsn = automaton->ainsn_list;
5570 ainsn != NULL;
5571 ainsn = ainsn->next_ainsn)
5572 if (ainsn->first_insn_with_same_reservs)
5574 insn_reserv_decl = ainsn->insn_reserv_decl;
5575 if (!special_decl_p (insn_reserv_decl))
5577 /* We process alt_states in the same order as they are
5578 present in the description. */
5579 for (alt_state = ainsn->alt_states;
5580 alt_state != NULL;
5581 alt_state = alt_state->next_alt_state)
5583 state2 = alt_state->state;
5584 if (!intersected_state_reservs_p (state, state2))
5586 state2 = states_union (state, state2, reservs_matter);
5587 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5589 state2->it_was_placed_in_stack_for_NDFA_forming
5590 = 1;
5591 state_stack.safe_push (state2);
5592 states_n++;
5593 if (progress_flag && states_n % 100 == 0)
5594 fprintf (stderr, ".");
5596 add_arc (state, state2, ainsn);
5597 if (!ndfa_flag)
5598 break;
5603 /* Add transition to advance cycle. */
5604 state2 = state_shift (state, reservs_matter);
5605 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5607 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5608 state_stack.safe_push (state2);
5609 states_n++;
5610 if (progress_flag && states_n % 100 == 0)
5611 fprintf (stderr, ".");
5613 add_arc (state, state2, automaton->advance_ainsn);
5617 /* Form lists of all arcs of STATE marked by the same ainsn. */
5618 static void
5619 form_arcs_marked_by_insn (state_t state)
5621 decl_t decl;
5622 arc_t arc;
5623 int i;
5625 for (i = 0; i < description->decls_num; i++)
5627 decl = description->decls [i];
5628 if (decl->mode == dm_insn_reserv)
5629 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5631 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5633 gcc_assert (arc->insn);
5634 arc->next_arc_marked_by_insn
5635 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5636 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5640 /* The function creates composed state (see comments for IR) from
5641 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5642 same insn. If the composed state is not in STATE_STACK yet, it is
5643 pushed into STATE_STACK. */
5645 static int
5646 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5647 vec<state_t> *state_stack)
5649 state_t state;
5650 alt_state_t alt_state, curr_alt_state;
5651 alt_state_t new_alt_state;
5652 arc_t curr_arc;
5653 arc_t next_arc;
5654 state_t state_in_table;
5655 state_t temp_state;
5656 alt_state_t canonical_alt_states_list;
5657 int alts_number;
5658 int new_state_p = 0;
5660 if (arcs_marked_by_insn == NULL)
5661 return new_state_p;
5662 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5663 state = arcs_marked_by_insn->to_state;
5664 else
5666 gcc_assert (ndfa_flag);
5667 /* Create composed state. */
5668 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5669 curr_alt_state = NULL;
5670 for (curr_arc = arcs_marked_by_insn;
5671 curr_arc != NULL;
5672 curr_arc = curr_arc->next_arc_marked_by_insn)
5673 if (curr_arc->to_state->component_states == NULL)
5675 new_alt_state = get_free_alt_state ();
5676 new_alt_state->next_alt_state = curr_alt_state;
5677 new_alt_state->state = curr_arc->to_state;
5678 curr_alt_state = new_alt_state;
5680 else
5681 for (alt_state = curr_arc->to_state->component_states;
5682 alt_state != NULL;
5683 alt_state = alt_state->next_sorted_alt_state)
5685 new_alt_state = get_free_alt_state ();
5686 new_alt_state->next_alt_state = curr_alt_state;
5687 new_alt_state->state = alt_state->state;
5688 gcc_assert (!alt_state->state->component_states);
5689 curr_alt_state = new_alt_state;
5691 /* There are not identical sets in the alt state list. */
5692 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5693 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5695 temp_state = state;
5696 state = canonical_alt_states_list->state;
5697 free_state (temp_state);
5699 else
5701 state->component_states = canonical_alt_states_list;
5702 state_in_table = insert_state (state);
5703 if (state_in_table != state)
5705 gcc_assert
5706 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5707 free_state (state);
5708 state = state_in_table;
5710 else
5712 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5713 new_state_p = 1;
5714 for (curr_alt_state = state->component_states;
5715 curr_alt_state != NULL;
5716 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5717 for (curr_arc = first_out_arc (curr_alt_state->state);
5718 curr_arc != NULL;
5719 curr_arc = next_out_arc (curr_arc))
5720 if (!collapse_flag
5721 /* When producing collapse-NDFA transitions, we
5722 only add advance-cycle transitions to the
5723 collapsed states. */
5724 || (curr_arc->insn->insn_reserv_decl
5725 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
5726 add_arc (state, curr_arc->to_state, curr_arc->insn);
5728 arcs_marked_by_insn->to_state = state;
5729 for (alts_number = 0,
5730 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5731 curr_arc != NULL;
5732 curr_arc = next_arc)
5734 next_arc = curr_arc->next_arc_marked_by_insn;
5735 remove_arc (original_state, curr_arc);
5736 alts_number++;
5740 if (!state->it_was_placed_in_stack_for_DFA_forming)
5742 state->it_was_placed_in_stack_for_DFA_forming = 1;
5743 state_stack->safe_push (state);
5745 return new_state_p;
5748 /* The function transforms nondeterministic AUTOMATON into
5749 deterministic. */
5751 static void
5752 NDFA_to_DFA (automaton_t automaton)
5754 state_t start_state;
5755 state_t state;
5756 decl_t decl;
5757 auto_vec<state_t> state_stack;
5758 int i;
5759 int states_n;
5761 /* Create the start state (empty state). */
5762 start_state = automaton->start_state;
5763 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5764 state_stack.safe_push (start_state);
5765 states_n = 1;
5766 while (state_stack.length () != 0)
5768 state = state_stack.pop ();
5769 form_arcs_marked_by_insn (state);
5770 for (i = 0; i < description->decls_num; i++)
5772 decl = description->decls [i];
5773 if (decl->mode == dm_insn_reserv
5774 && decl != collapse_ndfa_insn_decl
5775 && create_composed_state
5776 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5777 &state_stack))
5779 states_n++;
5780 if (progress_flag && states_n % 100 == 0)
5781 fprintf (stderr, ".");
5784 /* Add a transition to collapse the NDFA. */
5785 if (collapse_flag)
5787 if (state->component_states != NULL)
5789 state_t state2 = state->component_states->state;
5790 if (!state2->it_was_placed_in_stack_for_DFA_forming)
5792 state2->it_was_placed_in_stack_for_DFA_forming = 1;
5793 state_stack.safe_push (state2);
5795 add_arc (state, state2, automaton->collapse_ainsn);
5797 else
5798 add_arc (state, state, automaton->collapse_ainsn);
5803 /* The following variable value is current number (1, 2, ...) of passing
5804 graph of states. */
5805 static int curr_state_graph_pass_num;
5807 /* This recursive function passes all states achieved from START_STATE
5808 and applies APPLIED_FUNC to them. */
5809 static void
5810 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5812 arc_t arc;
5814 if (start_state->pass_num == curr_state_graph_pass_num)
5815 return;
5816 start_state->pass_num = curr_state_graph_pass_num;
5817 (*applied_func) (start_state);
5818 for (arc = first_out_arc (start_state);
5819 arc != NULL;
5820 arc = next_out_arc (arc))
5821 pass_state_graph (arc->to_state, applied_func);
5824 /* This recursive function passes all states of AUTOMATON and applies
5825 APPLIED_FUNC to them. */
5826 static void
5827 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5829 curr_state_graph_pass_num++;
5830 pass_state_graph (automaton->start_state, applied_func);
5833 /* The function initializes code for passing of all states. */
5834 static void
5835 initiate_pass_states (void)
5837 curr_state_graph_pass_num = 0;
5840 /* The following vla is used for storing pointers to all achieved
5841 states. */
5842 static vec<state_t> all_achieved_states;
5844 /* This function is called by function pass_states to add an achieved
5845 STATE. */
5846 static void
5847 add_achieved_state (state_t state)
5849 all_achieved_states.safe_push (state);
5852 /* The function sets up equivalence numbers of insns which mark all
5853 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5854 nonzero value) or by equiv_class_num_2 of the destination state. */
5855 static void
5856 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5858 arc_t arc;
5860 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5862 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5863 arc->insn->insn_reserv_decl->equiv_class_num
5864 = (odd_iteration_flag
5865 ? arc->to_state->equiv_class_num_1
5866 : arc->to_state->equiv_class_num_2);
5867 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5871 /* The function clears equivalence numbers and alt_states in all insns
5872 which mark all out arcs of STATE. */
5873 static void
5874 clear_arc_insns_equiv_num (state_t state)
5876 arc_t arc;
5878 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5879 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5883 /* The following function returns TRUE if STATE reserves the unit with
5884 UNIT_NUM on the first cycle. */
5885 static int
5886 first_cycle_unit_presence (state_t state, int unit_num)
5888 alt_state_t alt_state;
5890 if (state->component_states == NULL)
5891 return test_unit_reserv (state->reservs, 0, unit_num);
5892 else
5894 for (alt_state = state->component_states;
5895 alt_state != NULL;
5896 alt_state = alt_state->next_sorted_alt_state)
5897 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5898 return true;
5900 return false;
5903 /* This fills in the presence_signature[] member of STATE. */
5904 static void
5905 cache_presence (state_t state)
5907 int i, num = 0;
5908 unsigned int sz;
5909 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5910 / (sizeof (int) * CHAR_BIT);
5912 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5913 for (i = 0; i < description->units_num; i++)
5914 if (units_array [i]->query_p)
5916 int presence1_p = first_cycle_unit_presence (state, i);
5917 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5918 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5919 num++;
5923 /* The function returns nonzero value if STATE is not equivalent to
5924 ANOTHER_STATE from the same current partition on equivalence
5925 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5926 output arcs. Iteration of making equivalence partition is defined
5927 by ODD_ITERATION_FLAG. */
5928 static int
5929 state_is_differed (state_t state, state_t another_state,
5930 int odd_iteration_flag)
5932 arc_t arc;
5933 unsigned int sz, si;
5935 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5937 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5938 / (sizeof (int) * CHAR_BIT);
5940 for (si = 0; si < sz; si++)
5941 gcc_assert (state->presence_signature[si]
5942 == another_state->presence_signature[si]);
5944 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5946 if ((odd_iteration_flag
5947 ? arc->to_state->equiv_class_num_1
5948 : arc->to_state->equiv_class_num_2)
5949 != arc->insn->insn_reserv_decl->equiv_class_num)
5950 return 1;
5953 return 0;
5956 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5957 and return -1, 0 or 1. This function can be used as predicate for
5958 qsort(). It requires the member presence_signature[] of both
5959 states be filled. */
5960 static int
5961 compare_states_for_equiv (const void *state_ptr_1,
5962 const void *state_ptr_2)
5964 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5965 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5966 unsigned int sz, si;
5967 if (s1->num_out_arcs < s2->num_out_arcs)
5968 return -1;
5969 else if (s1->num_out_arcs > s2->num_out_arcs)
5970 return 1;
5972 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5973 / (sizeof (int) * CHAR_BIT);
5975 for (si = 0; si < sz; si++)
5976 if (s1->presence_signature[si] < s2->presence_signature[si])
5977 return -1;
5978 else if (s1->presence_signature[si] > s2->presence_signature[si])
5979 return 1;
5980 return 0;
5983 /* The function makes initial partition of STATES on equivalent
5984 classes and saves it into CLASSES. This function requires the input
5985 to be sorted via compare_states_for_equiv(). */
5986 static int
5987 init_equiv_class (vec<state_t> states, vec<state_t> *classes)
5989 size_t i;
5990 state_t prev = 0;
5991 int class_num = 1;
5993 classes->create (150);
5994 for (i = 0; i < states.length (); i++)
5996 state_t state = states[i];
5997 if (prev)
5999 if (compare_states_for_equiv (&prev, &state) != 0)
6001 classes->safe_push (prev);
6002 class_num++;
6003 prev = NULL;
6006 state->equiv_class_num_1 = class_num;
6007 state->next_equiv_class_state = prev;
6008 prev = state;
6010 if (prev)
6011 classes->safe_push (prev);
6012 return class_num;
6015 /* The function copies pointers to equivalent states from vla FROM
6016 into vla TO. */
6017 static void
6018 copy_equiv_class (vec<state_t> *to, vec<state_t> from)
6020 to->release ();
6021 *to = from.copy ();
6024 /* The function processes equivalence class given by its first state,
6025 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6026 are not equivalent states, the function partitions the class
6027 removing nonequivalent states and placing them in
6028 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6029 assigns it to the state equivalence number. If the class has been
6030 partitioned, the function returns nonzero value. */
6031 static int
6032 partition_equiv_class (state_t first_state, int odd_iteration_flag,
6033 vec<state_t> *next_iteration_classes,
6034 int *new_equiv_class_num_ptr)
6036 state_t new_equiv_class;
6037 int partition_p;
6038 state_t curr_state;
6039 state_t prev_state;
6040 state_t next_state;
6042 partition_p = 0;
6044 while (first_state != NULL)
6046 new_equiv_class = NULL;
6047 if (first_state->next_equiv_class_state != NULL)
6049 /* There are more one states in the class equivalence. */
6050 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6051 for (prev_state = first_state,
6052 curr_state = first_state->next_equiv_class_state;
6053 curr_state != NULL;
6054 curr_state = next_state)
6056 next_state = curr_state->next_equiv_class_state;
6057 if (state_is_differed (curr_state, first_state,
6058 odd_iteration_flag))
6060 /* Remove curr state from the class equivalence. */
6061 prev_state->next_equiv_class_state = next_state;
6062 /* Add curr state to the new class equivalence. */
6063 curr_state->next_equiv_class_state = new_equiv_class;
6064 if (new_equiv_class == NULL)
6065 (*new_equiv_class_num_ptr)++;
6066 if (odd_iteration_flag)
6067 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6068 else
6069 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6070 new_equiv_class = curr_state;
6071 partition_p = 1;
6073 else
6074 prev_state = curr_state;
6076 clear_arc_insns_equiv_num (first_state);
6078 if (new_equiv_class != NULL)
6079 next_iteration_classes->safe_push (new_equiv_class);
6080 first_state = new_equiv_class;
6082 return partition_p;
6085 /* The function finds equivalent states of AUTOMATON. */
6086 static void
6087 evaluate_equiv_classes (automaton_t automaton, vec<state_t> *equiv_classes)
6089 int new_equiv_class_num;
6090 int odd_iteration_flag;
6091 int finish_flag;
6092 vec<state_t> next_iteration_classes;
6093 size_t i;
6095 all_achieved_states.create (1500);
6096 pass_states (automaton, add_achieved_state);
6097 pass_states (automaton, cache_presence);
6098 all_achieved_states.qsort (compare_states_for_equiv);
6100 odd_iteration_flag = 0;
6101 new_equiv_class_num = init_equiv_class (all_achieved_states,
6102 &next_iteration_classes);
6106 odd_iteration_flag = !odd_iteration_flag;
6107 finish_flag = 1;
6108 copy_equiv_class (equiv_classes, next_iteration_classes);
6110 /* Transfer equiv numbers for the next iteration. */
6111 for (i = 0; i < all_achieved_states.length (); i++)
6112 if (odd_iteration_flag)
6113 all_achieved_states[i]->equiv_class_num_2
6114 = all_achieved_states[i]->equiv_class_num_1;
6115 else
6116 all_achieved_states[i]->equiv_class_num_1
6117 = all_achieved_states[i]->equiv_class_num_2;
6119 for (i = 0; i < equiv_classes->length (); i++)
6120 if (partition_equiv_class ((*equiv_classes)[i],
6121 odd_iteration_flag,
6122 &next_iteration_classes,
6123 &new_equiv_class_num))
6124 finish_flag = 0;
6126 while (!finish_flag);
6127 next_iteration_classes.release ();
6128 all_achieved_states.release ();
6131 /* The function merges equivalent states of AUTOMATON. */
6132 static void
6133 merge_states (automaton_t automaton, vec<state_t> equiv_classes)
6135 state_t curr_state;
6136 state_t new_state;
6137 state_t first_class_state;
6138 alt_state_t alt_states;
6139 alt_state_t alt_state, new_alt_state;
6140 arc_t curr_arc;
6141 arc_t next_arc;
6142 size_t i;
6144 /* Create states corresponding to equivalence classes containing two
6145 or more states. */
6146 for (i = 0; i < equiv_classes.length (); i++)
6148 curr_state = equiv_classes[i];
6149 if (curr_state->next_equiv_class_state != NULL)
6151 /* There are more one states in the class equivalence. */
6152 /* Create new compound state. */
6153 new_state = get_free_state (0, automaton);
6154 alt_states = NULL;
6155 first_class_state = curr_state;
6156 for (curr_state = first_class_state;
6157 curr_state != NULL;
6158 curr_state = curr_state->next_equiv_class_state)
6160 curr_state->equiv_class_state = new_state;
6161 if (curr_state->component_states == NULL)
6163 new_alt_state = get_free_alt_state ();
6164 new_alt_state->state = curr_state;
6165 new_alt_state->next_alt_state = alt_states;
6166 alt_states = new_alt_state;
6168 else
6169 for (alt_state = curr_state->component_states;
6170 alt_state != NULL;
6171 alt_state = alt_state->next_sorted_alt_state)
6173 new_alt_state = get_free_alt_state ();
6174 new_alt_state->state = alt_state->state;
6175 new_alt_state->next_alt_state = alt_states;
6176 alt_states = new_alt_state;
6179 /* It is important that alt states were sorted before and
6180 after merging to have the same querying results. */
6181 new_state->component_states = uniq_sort_alt_states (alt_states);
6183 else
6184 curr_state->equiv_class_state = curr_state;
6187 for (i = 0; i < equiv_classes.length (); i++)
6189 curr_state = equiv_classes[i];
6190 if (curr_state->next_equiv_class_state != NULL)
6192 first_class_state = curr_state;
6193 /* Create new arcs output from the state corresponding to
6194 equiv class. */
6195 for (curr_arc = first_out_arc (first_class_state);
6196 curr_arc != NULL;
6197 curr_arc = next_out_arc (curr_arc))
6198 add_arc (first_class_state->equiv_class_state,
6199 curr_arc->to_state->equiv_class_state,
6200 curr_arc->insn);
6201 /* Delete output arcs from states of given class equivalence. */
6202 for (curr_state = first_class_state;
6203 curr_state != NULL;
6204 curr_state = curr_state->next_equiv_class_state)
6206 if (automaton->start_state == curr_state)
6207 automaton->start_state = curr_state->equiv_class_state;
6208 /* Delete the state and its output arcs. */
6209 for (curr_arc = first_out_arc (curr_state);
6210 curr_arc != NULL;
6211 curr_arc = next_arc)
6213 next_arc = next_out_arc (curr_arc);
6214 free_arc (curr_arc);
6218 else
6220 /* Change `to_state' of arcs output from the state of given
6221 equivalence class. */
6222 for (curr_arc = first_out_arc (curr_state);
6223 curr_arc != NULL;
6224 curr_arc = next_out_arc (curr_arc))
6225 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6230 /* The function sets up new_cycle_p for states if there is arc to the
6231 state marked by advance_cycle_insn_decl. */
6232 static void
6233 set_new_cycle_flags (state_t state)
6235 arc_t arc;
6237 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6238 if (arc->insn->insn_reserv_decl
6239 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6240 arc->to_state->new_cycle_p = 1;
6243 /* The top level function for minimization of deterministic
6244 AUTOMATON. */
6245 static void
6246 minimize_DFA (automaton_t automaton)
6248 auto_vec<state_t> equiv_classes;
6250 evaluate_equiv_classes (automaton, &equiv_classes);
6251 merge_states (automaton, equiv_classes);
6252 pass_states (automaton, set_new_cycle_flags);
6255 /* Values of two variables are counted number of states and arcs in an
6256 automaton. */
6257 static int curr_counted_states_num;
6258 static int curr_counted_arcs_num;
6260 /* The function is called by function `pass_states' to count states
6261 and arcs of an automaton. */
6262 static void
6263 incr_states_and_arcs_nums (state_t state)
6265 arc_t arc;
6267 curr_counted_states_num++;
6268 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6269 curr_counted_arcs_num++;
6272 /* The function counts states and arcs of AUTOMATON. */
6273 static void
6274 count_states_and_arcs (automaton_t automaton, int *states_num,
6275 int *arcs_num)
6277 curr_counted_states_num = 0;
6278 curr_counted_arcs_num = 0;
6279 pass_states (automaton, incr_states_and_arcs_nums);
6280 *states_num = curr_counted_states_num;
6281 *arcs_num = curr_counted_arcs_num;
6284 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6285 recognition after checking and simplifying IR of the
6286 description. */
6287 static void
6288 build_automaton (automaton_t automaton)
6290 int states_num;
6291 int arcs_num;
6293 ticker_on (&NDFA_time);
6294 if (progress_flag)
6296 if (automaton->corresponding_automaton_decl == NULL)
6297 fprintf (stderr, "Create anonymous automaton");
6298 else
6299 fprintf (stderr, "Create automaton `%s'",
6300 automaton->corresponding_automaton_decl->name);
6301 fprintf (stderr, " (1 dot is 100 new states):");
6303 make_automaton (automaton);
6304 if (progress_flag)
6305 fprintf (stderr, " done\n");
6306 ticker_off (&NDFA_time);
6307 count_states_and_arcs (automaton, &states_num, &arcs_num);
6308 automaton->NDFA_states_num = states_num;
6309 automaton->NDFA_arcs_num = arcs_num;
6310 ticker_on (&NDFA_to_DFA_time);
6311 if (progress_flag)
6313 if (automaton->corresponding_automaton_decl == NULL)
6314 fprintf (stderr, "Make anonymous DFA");
6315 else
6316 fprintf (stderr, "Make DFA `%s'",
6317 automaton->corresponding_automaton_decl->name);
6318 fprintf (stderr, " (1 dot is 100 new states):");
6320 NDFA_to_DFA (automaton);
6321 if (progress_flag)
6322 fprintf (stderr, " done\n");
6323 ticker_off (&NDFA_to_DFA_time);
6324 count_states_and_arcs (automaton, &states_num, &arcs_num);
6325 automaton->DFA_states_num = states_num;
6326 automaton->DFA_arcs_num = arcs_num;
6327 if (!no_minimization_flag)
6329 ticker_on (&minimize_time);
6330 if (progress_flag)
6332 if (automaton->corresponding_automaton_decl == NULL)
6333 fprintf (stderr, "Minimize anonymous DFA...");
6334 else
6335 fprintf (stderr, "Minimize DFA `%s'...",
6336 automaton->corresponding_automaton_decl->name);
6338 minimize_DFA (automaton);
6339 if (progress_flag)
6340 fprintf (stderr, "done\n");
6341 ticker_off (&minimize_time);
6342 count_states_and_arcs (automaton, &states_num, &arcs_num);
6343 automaton->minimal_DFA_states_num = states_num;
6344 automaton->minimal_DFA_arcs_num = arcs_num;
6350 /* The page contains code for enumeration of all states of an automaton. */
6352 /* Variable used for enumeration of all states of an automaton. Its
6353 value is current number of automaton states. */
6354 static int curr_state_order_num;
6356 /* The function is called by function `pass_states' for enumerating
6357 states. */
6358 static void
6359 set_order_state_num (state_t state)
6361 state->order_state_num = curr_state_order_num;
6362 curr_state_order_num++;
6365 /* The function enumerates all states of AUTOMATON. */
6366 static void
6367 enumerate_states (automaton_t automaton)
6369 curr_state_order_num = 0;
6370 pass_states (automaton, set_order_state_num);
6371 automaton->achieved_states_num = curr_state_order_num;
6376 /* The page contains code for finding equivalent automaton insns
6377 (ainsns). */
6379 /* The function inserts AINSN into cyclic list
6380 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6381 static ainsn_t
6382 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6383 ainsn_t cyclic_equiv_class_insn_list)
6385 if (cyclic_equiv_class_insn_list == NULL)
6386 ainsn->next_equiv_class_insn = ainsn;
6387 else
6389 ainsn->next_equiv_class_insn
6390 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6391 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6393 return ainsn;
6396 /* The function deletes equiv_class_insn into cyclic list of
6397 equivalent ainsns. */
6398 static void
6399 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6401 ainsn_t curr_equiv_class_insn;
6402 ainsn_t prev_equiv_class_insn;
6404 prev_equiv_class_insn = equiv_class_insn;
6405 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6406 curr_equiv_class_insn != equiv_class_insn;
6407 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6408 prev_equiv_class_insn = curr_equiv_class_insn;
6409 if (prev_equiv_class_insn != equiv_class_insn)
6410 prev_equiv_class_insn->next_equiv_class_insn
6411 = equiv_class_insn->next_equiv_class_insn;
6414 /* The function processes AINSN of a state in order to find equivalent
6415 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6416 state. */
6417 static void
6418 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6420 ainsn_t next_insn;
6421 ainsn_t curr_insn;
6422 ainsn_t cyclic_insn_list;
6423 arc_t arc;
6425 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6426 curr_insn = ainsn;
6427 /* New class of ainsns which are not equivalent to given ainsn. */
6428 cyclic_insn_list = NULL;
6431 next_insn = curr_insn->next_equiv_class_insn;
6432 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6433 if (arc == NULL
6434 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6435 != arc->to_state))
6437 delete_ainsn_from_equiv_class (curr_insn);
6438 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6439 cyclic_insn_list);
6441 curr_insn = next_insn;
6443 while (curr_insn != ainsn);
6446 /* The function processes STATE in order to find equivalent ainsns. */
6447 static void
6448 process_state_for_insn_equiv_partition (state_t state)
6450 arc_t arc;
6451 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6453 /* Process insns of the arcs. */
6454 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6455 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6456 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6457 process_insn_equiv_class (arc->insn, insn_arcs_array);
6459 free (insn_arcs_array);
6462 /* The function searches for equivalent ainsns of AUTOMATON. */
6463 static void
6464 set_insn_equiv_classes (automaton_t automaton)
6466 ainsn_t ainsn;
6467 ainsn_t first_insn;
6468 ainsn_t curr_insn;
6469 ainsn_t cyclic_insn_list;
6470 ainsn_t insn_with_same_reservs;
6471 int equiv_classes_num;
6473 /* All insns are included in one equivalence class. */
6474 cyclic_insn_list = NULL;
6475 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6476 if (ainsn->first_insn_with_same_reservs)
6477 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6478 cyclic_insn_list);
6479 /* Process insns in order to make equivalence partition. */
6480 pass_states (automaton, process_state_for_insn_equiv_partition);
6481 /* Enumerate equiv classes. */
6482 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6483 /* Set undefined value. */
6484 ainsn->insn_equiv_class_num = -1;
6485 equiv_classes_num = 0;
6486 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6487 if (ainsn->insn_equiv_class_num < 0)
6489 first_insn = ainsn;
6490 gcc_assert (first_insn->first_insn_with_same_reservs);
6491 first_insn->first_ainsn_with_given_equivalence_num = 1;
6492 curr_insn = first_insn;
6495 for (insn_with_same_reservs = curr_insn;
6496 insn_with_same_reservs != NULL;
6497 insn_with_same_reservs
6498 = insn_with_same_reservs->next_same_reservs_insn)
6499 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6500 curr_insn = curr_insn->next_equiv_class_insn;
6502 while (curr_insn != first_insn);
6503 equiv_classes_num++;
6505 automaton->insn_equiv_classes_num = equiv_classes_num;
6510 /* This page contains code for creating DFA(s) and calls functions
6511 building them. */
6514 /* The following value is used to prevent floating point overflow for
6515 estimating an automaton bound. The value should be less DBL_MAX on
6516 the host machine. We use here approximate minimum of maximal
6517 double floating point value required by ANSI C standard. It
6518 will work for non ANSI sun compiler too. */
6520 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6522 /* The function estimate size of the single DFA used by PHR (pipeline
6523 hazards recognizer). */
6524 static double
6525 estimate_one_automaton_bound (void)
6527 decl_t decl;
6528 double one_automaton_estimation_bound;
6529 double root_value;
6530 int i;
6532 one_automaton_estimation_bound = 1.0;
6533 for (i = 0; i < description->decls_num; i++)
6535 decl = description->decls [i];
6536 if (decl->mode == dm_unit)
6538 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6539 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6540 / automata_num);
6541 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6542 > one_automaton_estimation_bound)
6543 one_automaton_estimation_bound *= root_value;
6546 return one_automaton_estimation_bound;
6549 /* The function compares unit declarations according to their maximal
6550 cycle in reservations. */
6551 static int
6552 compare_max_occ_cycle_nums (const void *unit_decl_1,
6553 const void *unit_decl_2)
6555 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6556 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6557 return 1;
6558 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6559 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6560 return 0;
6561 else
6562 return -1;
6565 /* The function makes heuristic assigning automata to units. Actually
6566 efficacy of the algorithm has been checked yet??? */
6568 static void
6569 units_to_automata_heuristic_distr (void)
6571 double estimation_bound;
6572 int automaton_num;
6573 int rest_units_num;
6574 double bound_value;
6575 unit_decl_t *unit_decls;
6576 int i, j;
6578 if (description->units_num == 0)
6579 return;
6580 estimation_bound = estimate_one_automaton_bound ();
6581 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6583 for (i = 0, j = 0; i < description->decls_num; i++)
6584 if (description->decls[i]->mode == dm_unit)
6585 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6586 gcc_assert (j == description->units_num);
6588 qsort (unit_decls, description->units_num,
6589 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6591 automaton_num = 0;
6592 bound_value = unit_decls[0]->max_occ_cycle_num;
6593 unit_decls[0]->corresponding_automaton_num = automaton_num;
6595 for (i = 1; i < description->units_num; i++)
6597 rest_units_num = description->units_num - i + 1;
6598 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6599 if (automaton_num < automata_num - 1
6600 && ((automata_num - automaton_num - 1 == rest_units_num)
6601 || (bound_value
6602 > (estimation_bound
6603 / unit_decls[i]->max_occ_cycle_num))))
6605 bound_value = unit_decls[i]->max_occ_cycle_num;
6606 automaton_num++;
6608 else
6609 bound_value *= unit_decls[i]->max_occ_cycle_num;
6610 unit_decls[i]->corresponding_automaton_num = automaton_num;
6612 gcc_assert (automaton_num == automata_num - 1);
6613 free (unit_decls);
6616 /* The functions creates automaton insns for each automata. Automaton
6617 insn is simply insn for given automaton which makes reservation
6618 only of units of the automaton. */
6619 static void
6620 create_ainsns (automaton_t automaton)
6622 decl_t decl;
6623 ainsn_t first_ainsn;
6624 ainsn_t curr_ainsn;
6625 ainsn_t prev_ainsn;
6626 int i;
6628 first_ainsn = NULL;
6629 prev_ainsn = NULL;
6630 for (i = 0; i < description->decls_num; i++)
6632 decl = description->decls [i];
6633 if (decl->mode == dm_insn_reserv)
6635 curr_ainsn = XCREATENODE (struct ainsn);
6636 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6637 curr_ainsn->important_p = FALSE;
6638 curr_ainsn->next_ainsn = NULL;
6639 if (prev_ainsn == NULL)
6640 first_ainsn = curr_ainsn;
6641 else
6642 prev_ainsn->next_ainsn = curr_ainsn;
6643 if (decl == advance_cycle_insn_decl)
6644 automaton->advance_ainsn = curr_ainsn;
6645 else if (decl == collapse_ndfa_insn_decl)
6646 automaton->collapse_ainsn = curr_ainsn;
6647 prev_ainsn = curr_ainsn;
6650 automaton->ainsn_list = first_ainsn;
6653 /* The function assigns automata to units according to constructions
6654 `define_automaton' in the description. */
6655 static void
6656 units_to_automata_distr (void)
6658 decl_t decl;
6659 int i;
6661 for (i = 0; i < description->decls_num; i++)
6663 decl = description->decls [i];
6664 if (decl->mode == dm_unit)
6666 if (DECL_UNIT (decl)->automaton_decl == NULL
6667 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6668 == NULL))
6669 /* Distribute to the first automaton. */
6670 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6671 else
6672 DECL_UNIT (decl)->corresponding_automaton_num
6673 = (DECL_UNIT (decl)->automaton_decl
6674 ->corresponding_automaton->automaton_order_num);
6679 /* The function creates DFA(s) for fast pipeline hazards recognition
6680 after checking and simplifying IR of the description. */
6681 static void
6682 create_automata (void)
6684 automaton_t curr_automaton;
6685 automaton_t prev_automaton;
6686 decl_t decl;
6687 int curr_automaton_num;
6688 int i;
6690 if (automata_num != 0)
6692 units_to_automata_heuristic_distr ();
6693 for (prev_automaton = NULL, curr_automaton_num = 0;
6694 curr_automaton_num < automata_num;
6695 curr_automaton_num++, prev_automaton = curr_automaton)
6697 curr_automaton = XCREATENODE (struct automaton);
6698 create_ainsns (curr_automaton);
6699 curr_automaton->corresponding_automaton_decl = NULL;
6700 curr_automaton->next_automaton = NULL;
6701 curr_automaton->automaton_order_num = curr_automaton_num;
6702 if (prev_automaton == NULL)
6703 description->first_automaton = curr_automaton;
6704 else
6705 prev_automaton->next_automaton = curr_automaton;
6708 else
6710 curr_automaton_num = 0;
6711 prev_automaton = NULL;
6712 for (i = 0; i < description->decls_num; i++)
6714 decl = description->decls [i];
6715 if (decl->mode == dm_automaton
6716 && DECL_AUTOMATON (decl)->automaton_is_used)
6718 curr_automaton = XCREATENODE (struct automaton);
6719 create_ainsns (curr_automaton);
6720 curr_automaton->corresponding_automaton_decl
6721 = DECL_AUTOMATON (decl);
6722 curr_automaton->next_automaton = NULL;
6723 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6724 curr_automaton->automaton_order_num = curr_automaton_num;
6725 if (prev_automaton == NULL)
6726 description->first_automaton = curr_automaton;
6727 else
6728 prev_automaton->next_automaton = curr_automaton;
6729 curr_automaton_num++;
6730 prev_automaton = curr_automaton;
6733 if (curr_automaton_num == 0)
6735 curr_automaton = XCREATENODE (struct automaton);
6736 create_ainsns (curr_automaton);
6737 curr_automaton->corresponding_automaton_decl = NULL;
6738 curr_automaton->next_automaton = NULL;
6739 description->first_automaton = curr_automaton;
6741 units_to_automata_distr ();
6743 NDFA_time = create_ticker ();
6744 ticker_off (&NDFA_time);
6745 NDFA_to_DFA_time = create_ticker ();
6746 ticker_off (&NDFA_to_DFA_time);
6747 minimize_time = create_ticker ();
6748 ticker_off (&minimize_time);
6749 equiv_time = create_ticker ();
6750 ticker_off (&equiv_time);
6751 for (curr_automaton = description->first_automaton;
6752 curr_automaton != NULL;
6753 curr_automaton = curr_automaton->next_automaton)
6755 if (progress_flag)
6757 if (curr_automaton->corresponding_automaton_decl == NULL)
6758 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6759 else
6760 fprintf (stderr, "Prepare automaton `%s' creation...",
6761 curr_automaton->corresponding_automaton_decl->name);
6763 create_alt_states (curr_automaton);
6764 form_ainsn_with_same_reservs (curr_automaton);
6765 if (progress_flag)
6766 fprintf (stderr, "done\n");
6767 build_automaton (curr_automaton);
6768 enumerate_states (curr_automaton);
6769 ticker_on (&equiv_time);
6770 set_insn_equiv_classes (curr_automaton);
6771 ticker_off (&equiv_time);
6777 /* This page contains code for forming string representation of
6778 regexp. The representation is formed on IR obstack. So you should
6779 not work with IR obstack between regexp_representation and
6780 finish_regexp_representation calls. */
6782 /* This recursive function forms string representation of regexp
6783 (without tailing '\0'). */
6784 static void
6785 form_regexp (regexp_t regexp)
6787 int i;
6789 switch (regexp->mode)
6791 case rm_unit: case rm_reserv:
6793 const char *name = (regexp->mode == rm_unit
6794 ? REGEXP_UNIT (regexp)->name
6795 : REGEXP_RESERV (regexp)->name);
6797 obstack_grow (&irp, name, strlen (name));
6798 break;
6801 case rm_sequence:
6802 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6804 if (i != 0)
6805 obstack_1grow (&irp, ',');
6806 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6808 break;
6810 case rm_allof:
6811 obstack_1grow (&irp, '(');
6812 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6814 if (i != 0)
6815 obstack_1grow (&irp, '+');
6816 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6817 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6818 obstack_1grow (&irp, '(');
6819 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6820 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6821 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6822 obstack_1grow (&irp, ')');
6824 obstack_1grow (&irp, ')');
6825 break;
6827 case rm_oneof:
6828 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6830 if (i != 0)
6831 obstack_1grow (&irp, '|');
6832 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6833 obstack_1grow (&irp, '(');
6834 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6835 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6836 obstack_1grow (&irp, ')');
6838 break;
6840 case rm_repeat:
6842 char digits [30];
6844 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6845 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6846 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6847 obstack_1grow (&irp, '(');
6848 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6849 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6850 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6851 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6852 obstack_1grow (&irp, ')');
6853 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6854 obstack_grow (&irp, digits, strlen (digits));
6855 break;
6858 case rm_nothing:
6859 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6860 break;
6862 default:
6863 gcc_unreachable ();
6867 /* The function returns string representation of REGEXP on IR
6868 obstack. */
6869 static const char *
6870 regexp_representation (regexp_t regexp)
6872 form_regexp (regexp);
6873 obstack_1grow (&irp, '\0');
6874 return (char *) obstack_base (&irp);
6877 /* The function frees memory allocated for last formed string
6878 representation of regexp. */
6879 static void
6880 finish_regexp_representation (void)
6882 int length = obstack_object_size (&irp);
6884 obstack_blank_fast (&irp, -length);
6889 /* This page contains code for output PHR (pipeline hazards recognizer). */
6891 /* The function outputs minimal C type which is sufficient for
6892 representation numbers in range min_range_value and
6893 max_range_value. Because host machine and build machine may be
6894 different, we use here minimal values required by ANSI C standard
6895 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6896 approximation. */
6898 static void
6899 output_range_type (FILE *f, long int min_range_value,
6900 long int max_range_value)
6902 if (min_range_value >= 0 && max_range_value <= 255)
6903 fprintf (f, "unsigned char");
6904 else if (min_range_value >= -127 && max_range_value <= 127)
6905 fprintf (f, "signed char");
6906 else if (min_range_value >= 0 && max_range_value <= 65535)
6907 fprintf (f, "unsigned short");
6908 else if (min_range_value >= -32767 && max_range_value <= 32767)
6909 fprintf (f, "short");
6910 else
6911 fprintf (f, "int");
6914 /* The function outputs all initialization values of VECT. */
6915 static void
6916 output_vect (vla_hwint_t vect)
6918 int els_on_line;
6919 size_t vect_length = vect.length ();
6920 size_t i;
6922 els_on_line = 1;
6923 if (vect_length == 0)
6924 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6925 else
6926 for (i = 0; i < vect_length; i++)
6928 fprintf (output_file, "%5ld", (long) vect[i]);
6929 if (els_on_line == 10)
6931 els_on_line = 0;
6932 fputs (",\n", output_file);
6934 else if (i < vect_length-1)
6935 fputs (", ", output_file);
6936 els_on_line++;
6940 /* The following is name of the structure which represents DFA(s) for
6941 PHR. */
6942 #define CHIP_NAME "DFA_chip"
6944 /* The following is name of member which represents state of a DFA for
6945 PHR. */
6946 static void
6947 output_chip_member_name (FILE *f, automaton_t automaton)
6949 if (automaton->corresponding_automaton_decl == NULL)
6950 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6951 else
6952 fprintf (f, "%s_automaton_state",
6953 automaton->corresponding_automaton_decl->name);
6956 /* The following is name of temporary variable which stores state of a
6957 DFA for PHR. */
6958 static void
6959 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6961 fprintf (f, "_");
6962 output_chip_member_name (f, automaton);
6965 /* This is name of macro value which is code of pseudo_insns
6966 representing advancing cpu cycle and collapsing the NDFA.
6967 Its value is used as internal code unknown insn. */
6968 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6969 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
6971 /* Output name of translate vector for given automaton. */
6972 static void
6973 output_translate_vect_name (FILE *f, automaton_t automaton)
6975 if (automaton->corresponding_automaton_decl == NULL)
6976 fprintf (f, "translate_%d", automaton->automaton_order_num);
6977 else
6978 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6981 /* Output name for simple transition table representation. */
6982 static void
6983 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6985 if (automaton->corresponding_automaton_decl == NULL)
6986 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6987 else
6988 fprintf (f, "%s_transitions",
6989 automaton->corresponding_automaton_decl->name);
6992 /* Output name of comb vector of the transition table for given
6993 automaton. */
6994 static void
6995 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6997 if (automaton->corresponding_automaton_decl == NULL)
6998 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6999 else
7000 fprintf (f, "%s_transitions",
7001 automaton->corresponding_automaton_decl->name);
7004 /* Output name of check vector of the transition table for given
7005 automaton. */
7006 static void
7007 output_trans_check_vect_name (FILE *f, automaton_t automaton)
7009 if (automaton->corresponding_automaton_decl == NULL)
7010 fprintf (f, "check_%d", automaton->automaton_order_num);
7011 else
7012 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7015 /* Output name of base vector of the transition table for given
7016 automaton. */
7017 static void
7018 output_trans_base_vect_name (FILE *f, automaton_t automaton)
7020 if (automaton->corresponding_automaton_decl == NULL)
7021 fprintf (f, "base_%d", automaton->automaton_order_num);
7022 else
7023 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7026 /* Output name of simple min issue delay table representation. */
7027 static void
7028 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7030 if (automaton->corresponding_automaton_decl == NULL)
7031 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7032 else
7033 fprintf (f, "%s_min_issue_delay",
7034 automaton->corresponding_automaton_decl->name);
7037 /* Output name of deadlock vector for given automaton. */
7038 static void
7039 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7041 if (automaton->corresponding_automaton_decl == NULL)
7042 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7043 else
7044 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7047 /* Output name of reserved units table for AUTOMATON into file F. */
7048 static void
7049 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7051 if (automaton->corresponding_automaton_decl == NULL)
7052 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7053 else
7054 fprintf (f, "%s_reserved_units",
7055 automaton->corresponding_automaton_decl->name);
7058 /* Name of the PHR interface macro. */
7059 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7061 /* Names of an internal functions: */
7062 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7064 /* This is external type of DFA(s) state. */
7065 #define STATE_TYPE_NAME "state_t"
7067 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7069 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7071 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7073 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7075 /* Name of cache of insn dfa codes. */
7076 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7078 /* Name of length of cache of insn dfa codes. */
7079 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7081 /* Names of the PHR interface functions: */
7082 #define SIZE_FUNC_NAME "state_size"
7084 #define TRANSITION_FUNC_NAME "state_transition"
7086 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7088 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7090 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7092 #define RESET_FUNC_NAME "state_reset"
7094 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7096 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7098 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7100 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7102 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7104 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7106 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7108 #define DFA_START_FUNC_NAME "dfa_start"
7110 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7112 /* Names of parameters of the PHR interface functions. */
7113 #define STATE_NAME "state"
7115 #define INSN_PARAMETER_NAME "insn"
7117 #define INSN2_PARAMETER_NAME "insn2"
7119 #define CHIP_PARAMETER_NAME "chip"
7121 #define FILE_PARAMETER_NAME "f"
7123 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7125 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7127 /* Names of the variables whose values are internal insn code of rtx
7128 insn. */
7129 #define INTERNAL_INSN_CODE_NAME "insn_code"
7131 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7133 /* Names of temporary variables in some functions. */
7134 #define TEMPORARY_VARIABLE_NAME "temp"
7136 #define I_VARIABLE_NAME "i"
7138 /* Name of result variable in some functions. */
7139 #define RESULT_VARIABLE_NAME "res"
7141 /* Name of function (attribute) to translate insn into internal insn
7142 code. */
7143 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7145 /* Name of function (attribute) to translate insn into internal insn
7146 code with caching. */
7147 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7149 /* Output C type which is used for representation of codes of states
7150 of AUTOMATON. */
7151 static void
7152 output_state_member_type (FILE *f, automaton_t automaton)
7154 output_range_type (f, 0, automaton->achieved_states_num);
7157 /* Output definition of the structure representing current DFA(s)
7158 state(s). */
7159 static void
7160 output_chip_definitions (void)
7162 automaton_t automaton;
7164 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7165 for (automaton = description->first_automaton;
7166 automaton != NULL;
7167 automaton = automaton->next_automaton)
7169 fprintf (output_file, " ");
7170 output_state_member_type (output_file, automaton);
7171 fprintf (output_file, " ");
7172 output_chip_member_name (output_file, automaton);
7173 fprintf (output_file, ";\n");
7175 fprintf (output_file, "};\n\n");
7176 #if 0
7177 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7178 #endif
7182 /* The function outputs translate vector of internal insn code into
7183 insn equivalence class number. The equivalence class number is
7184 used to access to table and vectors representing DFA(s). */
7185 static void
7186 output_translate_vect (automaton_t automaton)
7188 ainsn_t ainsn;
7189 int insn_value;
7190 vla_hwint_t translate_vect;
7192 translate_vect.create (description->insns_num);
7194 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7195 /* Undefined value */
7196 translate_vect.quick_push (automaton->insn_equiv_classes_num);
7198 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7199 translate_vect[ainsn->insn_reserv_decl->insn_num] =
7200 ainsn->insn_equiv_class_num;
7202 fprintf (output_file,
7203 "/* Vector translating external insn codes to internal ones.*/\n");
7204 fprintf (output_file, "static const ");
7205 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7206 fprintf (output_file, " ");
7207 output_translate_vect_name (output_file, automaton);
7208 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7209 output_vect (translate_vect);
7210 fprintf (output_file, "};\n\n");
7211 translate_vect.release ();
7214 /* The value in a table state x ainsn -> something which represents
7215 undefined value. */
7216 static int undefined_vect_el_value;
7218 /* The following function returns nonzero value if the best
7219 representation of the table is comb vector. */
7220 static int
7221 comb_vect_p (state_ainsn_table_t tab)
7223 if (no_comb_flag)
7224 return false;
7225 return (2 * tab->full_vect.length () > 5 * tab->comb_vect.length ());
7228 /* The following function creates new table for AUTOMATON. */
7229 static state_ainsn_table_t
7230 create_state_ainsn_table (automaton_t automaton)
7232 state_ainsn_table_t tab;
7233 int full_vect_length;
7234 int i;
7236 tab = XCREATENODE (struct state_ainsn_table);
7237 tab->automaton = automaton;
7239 tab->comb_vect.create (10000);
7240 tab->check_vect.create (10000);
7242 tab->base_vect.create (0);
7243 tab->base_vect.safe_grow (automaton->achieved_states_num);
7245 full_vect_length = (automaton->insn_equiv_classes_num
7246 * automaton->achieved_states_num);
7247 tab->full_vect.create (full_vect_length);
7248 for (i = 0; i < full_vect_length; i++)
7249 tab->full_vect.quick_push (undefined_vect_el_value);
7251 tab->min_base_vect_el_value = 0;
7252 tab->max_base_vect_el_value = 0;
7253 tab->min_comb_vect_el_value = 0;
7254 tab->max_comb_vect_el_value = 0;
7255 return tab;
7258 /* The following function outputs the best C representation of the
7259 table TAB of given TABLE_NAME. */
7260 static void
7261 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7262 void (*output_full_vect_name_func) (FILE *, automaton_t),
7263 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7264 void (*output_check_vect_name_func) (FILE *, automaton_t),
7265 void (*output_base_vect_name_func) (FILE *, automaton_t))
7267 if (!comb_vect_p (tab))
7269 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7270 fprintf (output_file, "static const ");
7271 output_range_type (output_file, tab->min_comb_vect_el_value,
7272 tab->max_comb_vect_el_value);
7273 fprintf (output_file, " ");
7274 (*output_full_vect_name_func) (output_file, tab->automaton);
7275 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7276 output_vect (tab->full_vect);
7277 fprintf (output_file, "};\n\n");
7279 else
7281 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7282 fprintf (output_file, "static const ");
7283 output_range_type (output_file, tab->min_comb_vect_el_value,
7284 tab->max_comb_vect_el_value);
7285 fprintf (output_file, " ");
7286 (*output_comb_vect_name_func) (output_file, tab->automaton);
7287 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7288 output_vect (tab->comb_vect);
7289 fprintf (output_file, "};\n\n");
7290 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7291 fprintf (output_file, "static const ");
7292 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7293 fprintf (output_file, " ");
7294 (*output_check_vect_name_func) (output_file, tab->automaton);
7295 fprintf (output_file, "[] = {\n");
7296 output_vect (tab->check_vect);
7297 fprintf (output_file, "};\n\n");
7298 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7299 fprintf (output_file, "static const ");
7300 output_range_type (output_file, tab->min_base_vect_el_value,
7301 tab->max_base_vect_el_value);
7302 fprintf (output_file, " ");
7303 (*output_base_vect_name_func) (output_file, tab->automaton);
7304 fprintf (output_file, "[] = {\n");
7305 output_vect (tab->base_vect);
7306 fprintf (output_file, "};\n\n");
7310 /* The following function adds vector VECT to table TAB as its line
7311 with number VECT_NUM. */
7312 static void
7313 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7315 int vect_length;
7316 size_t real_vect_length;
7317 int comb_vect_index;
7318 int comb_vect_els_num;
7319 int vect_index;
7320 int first_unempty_vect_index;
7321 int additional_els_num;
7322 int no_state_value;
7323 vect_el_t vect_el;
7324 int i;
7325 unsigned long vect_mask, comb_vect_mask;
7327 vect_length = vect.length ();
7328 gcc_assert (vect_length);
7329 gcc_assert (vect.last () != undefined_vect_el_value);
7330 real_vect_length = tab->automaton->insn_equiv_classes_num;
7331 /* Form full vector in the table: */
7333 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7334 if (tab->full_vect.length () < full_base + vect_length)
7335 tab->full_vect.safe_grow (full_base + vect_length);
7336 for (i = 0; i < vect_length; i++)
7337 tab->full_vect[full_base + i] = vect[i];
7340 /* The comb_vect min/max values are also used for the full vector, so
7341 compute them now. */
7342 for (vect_index = 0; vect_index < vect_length; vect_index++)
7343 if (vect[vect_index] != undefined_vect_el_value)
7345 vect_el_t x = vect[vect_index];
7346 gcc_assert (x >= 0);
7347 if (tab->max_comb_vect_el_value < x)
7348 tab->max_comb_vect_el_value = x;
7349 if (tab->min_comb_vect_el_value > x)
7350 tab->min_comb_vect_el_value = x;
7352 if (no_comb_flag)
7353 return;
7355 /* Form comb vector in the table: */
7356 gcc_assert (tab->comb_vect.length () == tab->check_vect.length ());
7358 comb_vect_els_num = tab->comb_vect.length ();
7359 for (first_unempty_vect_index = 0;
7360 first_unempty_vect_index < vect_length;
7361 first_unempty_vect_index++)
7362 if (vect[first_unempty_vect_index]
7363 != undefined_vect_el_value)
7364 break;
7366 /* Search for the place in comb vect for the inserted vect. */
7368 /* Slow case. */
7369 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7371 for (comb_vect_index = 0;
7372 comb_vect_index < comb_vect_els_num;
7373 comb_vect_index++)
7375 for (vect_index = first_unempty_vect_index;
7376 vect_index < vect_length
7377 && vect_index + comb_vect_index < comb_vect_els_num;
7378 vect_index++)
7379 if (vect[vect_index]
7380 != undefined_vect_el_value
7381 && (tab->comb_vect[vect_index + comb_vect_index]
7382 != undefined_vect_el_value))
7383 break;
7384 if (vect_index >= vect_length
7385 || vect_index + comb_vect_index >= comb_vect_els_num)
7386 break;
7388 goto found;
7391 /* Fast case. */
7392 vect_mask = 0;
7393 for (vect_index = first_unempty_vect_index;
7394 vect_index < vect_length;
7395 vect_index++)
7397 vect_mask = vect_mask << 1;
7398 if (vect[vect_index] != undefined_vect_el_value)
7399 vect_mask |= 1;
7402 /* Search for the place in comb vect for the inserted vect. */
7403 comb_vect_index = 0;
7404 if (comb_vect_els_num == 0)
7405 goto found;
7407 comb_vect_mask = 0;
7408 for (vect_index = first_unempty_vect_index;
7409 vect_index < vect_length && vect_index < comb_vect_els_num;
7410 vect_index++)
7412 comb_vect_mask <<= 1;
7413 if (vect_index + comb_vect_index < comb_vect_els_num
7414 && tab->comb_vect[vect_index + comb_vect_index]
7415 != undefined_vect_el_value)
7416 comb_vect_mask |= 1;
7418 if ((vect_mask & comb_vect_mask) == 0)
7419 goto found;
7421 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7422 comb_vect_index++, i++)
7424 comb_vect_mask = (comb_vect_mask << 1) | 1;
7425 comb_vect_mask ^= (tab->comb_vect[i]
7426 == undefined_vect_el_value);
7427 if ((vect_mask & comb_vect_mask) == 0)
7428 goto found;
7430 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7432 comb_vect_mask <<= 1;
7433 if ((vect_mask & comb_vect_mask) == 0)
7434 goto found;
7437 found:
7438 /* Slot was found. */
7439 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7440 if (additional_els_num < 0)
7441 additional_els_num = 0;
7442 /* Expand comb and check vectors. */
7443 vect_el = undefined_vect_el_value;
7444 no_state_value = tab->automaton->achieved_states_num;
7445 while (additional_els_num > 0)
7447 tab->comb_vect.safe_push (vect_el);
7448 tab->check_vect.safe_push (no_state_value);
7449 additional_els_num--;
7451 gcc_assert (tab->comb_vect.length ()
7452 >= comb_vect_index + real_vect_length);
7453 /* Fill comb and check vectors. */
7454 for (vect_index = 0; vect_index < vect_length; vect_index++)
7455 if (vect[vect_index] != undefined_vect_el_value)
7457 vect_el_t x = vect[vect_index];
7458 gcc_assert (tab->comb_vect[comb_vect_index + vect_index]
7459 == undefined_vect_el_value);
7460 gcc_assert (x >= 0);
7461 tab->comb_vect[comb_vect_index + vect_index] = x;
7462 tab->check_vect[comb_vect_index + vect_index] = vect_num;
7464 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7465 tab->max_comb_vect_el_value = undefined_vect_el_value;
7466 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7467 tab->min_comb_vect_el_value = undefined_vect_el_value;
7468 if (tab->max_base_vect_el_value < comb_vect_index)
7469 tab->max_base_vect_el_value = comb_vect_index;
7470 if (tab->min_base_vect_el_value > comb_vect_index)
7471 tab->min_base_vect_el_value = comb_vect_index;
7473 tab->base_vect[vect_num] = comb_vect_index;
7476 /* Return number of out arcs of STATE. */
7477 static int
7478 out_state_arcs_num (const_state_t state)
7480 int result;
7481 arc_t arc;
7483 result = 0;
7484 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7486 gcc_assert (arc->insn);
7487 if (arc->insn->first_ainsn_with_given_equivalence_num)
7488 result++;
7490 return result;
7493 /* Compare number of possible transitions from the states. */
7494 static int
7495 compare_transition_els_num (const void *state_ptr_1,
7496 const void *state_ptr_2)
7498 const int transition_els_num_1
7499 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7500 const int transition_els_num_2
7501 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7503 if (transition_els_num_1 < transition_els_num_2)
7504 return 1;
7505 else if (transition_els_num_1 == transition_els_num_2)
7506 return 0;
7507 else
7508 return -1;
7511 /* The function adds element EL_VALUE to vector VECT for a table state
7512 x AINSN. */
7513 static void
7514 add_vect_el (vla_hwint_t &vect, ainsn_t ainsn, int el_value)
7516 int equiv_class_num;
7517 int vect_index;
7519 gcc_assert (ainsn);
7520 equiv_class_num = ainsn->insn_equiv_class_num;
7521 for (vect_index = vect.length ();
7522 vect_index <= equiv_class_num;
7523 vect_index++)
7524 vect.safe_push (undefined_vect_el_value);
7525 vect[equiv_class_num] = el_value;
7528 /* This is for forming vector of states of an automaton. */
7529 static vec<state_t> output_states_vect;
7531 /* The function is called by function pass_states. The function adds
7532 STATE to `output_states_vect'. */
7533 static void
7534 add_states_vect_el (state_t state)
7536 output_states_vect.safe_push (state);
7539 /* Form and output vectors (comb, check, base or full vector)
7540 representing transition table of AUTOMATON. */
7541 static void
7542 output_trans_table (automaton_t automaton)
7544 size_t i;
7545 arc_t arc;
7546 vla_hwint_t transition_vect = vla_hwint_t ();
7548 undefined_vect_el_value = automaton->achieved_states_num;
7549 automaton->trans_table = create_state_ainsn_table (automaton);
7550 /* Create vect of pointers to states ordered by num of transitions
7551 from the state (state with the maximum num is the first). */
7552 output_states_vect.create (0);
7553 pass_states (automaton, add_states_vect_el);
7554 output_states_vect.qsort (compare_transition_els_num);
7556 for (i = 0; i < output_states_vect.length (); i++)
7558 transition_vect.truncate (0);
7559 for (arc = first_out_arc (output_states_vect[i]);
7560 arc != NULL;
7561 arc = next_out_arc (arc))
7563 gcc_assert (arc->insn);
7564 if (arc->insn->first_ainsn_with_given_equivalence_num)
7565 add_vect_el (transition_vect, arc->insn,
7566 arc->to_state->order_state_num);
7568 add_vect (automaton->trans_table,
7569 output_states_vect[i]->order_state_num,
7570 transition_vect);
7572 output_state_ainsn_table
7573 (automaton->trans_table, "state transitions",
7574 output_trans_full_vect_name, output_trans_comb_vect_name,
7575 output_trans_check_vect_name, output_trans_base_vect_name);
7577 output_states_vect.release ();
7578 transition_vect.release ();
7581 /* Form and output vectors representing minimal issue delay table of
7582 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7583 the ainsn. */
7584 static void
7585 output_min_issue_delay_table (automaton_t automaton)
7587 vla_hwint_t min_issue_delay_vect;
7588 vla_hwint_t compressed_min_issue_delay_vect;
7589 ainsn_t ainsn;
7590 size_t i;
7591 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7592 size_t cfactor;
7593 int changed;
7595 /* Create vect of pointers to states ordered by num of transitions
7596 from the state (state with the maximum num is the first). */
7597 output_states_vect.create (0);
7598 pass_states (automaton, add_states_vect_el);
7600 min_issue_delay_len = (output_states_vect.length ()
7601 * automaton->insn_equiv_classes_num);
7602 min_issue_delay_vect.create (min_issue_delay_len);
7603 for (i = 0; i < min_issue_delay_len; i++)
7604 min_issue_delay_vect.quick_push (-1);
7606 automaton->max_min_delay = 0;
7610 size_t state_no;
7612 changed = 0;
7614 for (state_no = 0; state_no < output_states_vect.length ();
7615 state_no++)
7617 state_t s = output_states_vect[state_no];
7618 arc_t arc;
7620 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7622 int k;
7624 size_t asn = s->order_state_num
7625 * automaton->insn_equiv_classes_num
7626 + arc->insn->insn_equiv_class_num;
7628 if (min_issue_delay_vect[asn])
7630 min_issue_delay_vect[asn] = (vect_el_t) 0;
7631 changed = 1;
7634 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7636 size_t n0, n1;
7637 vect_el_t delay0, delay1;
7639 n0 = s->order_state_num
7640 * automaton->insn_equiv_classes_num
7641 + k;
7642 n1 = arc->to_state->order_state_num
7643 * automaton->insn_equiv_classes_num
7644 + k;
7645 delay0 = min_issue_delay_vect[n0];
7646 delay1 = min_issue_delay_vect[n1];
7647 if (delay1 != -1)
7649 if (arc->insn->insn_reserv_decl
7650 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7651 delay1++;
7652 if (delay1 < delay0 || delay0 == -1)
7654 min_issue_delay_vect[n0] = delay1;
7655 changed = 1;
7662 while (changed);
7664 automaton->max_min_delay = 0;
7666 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7667 if (ainsn->first_ainsn_with_given_equivalence_num)
7669 for (i = 0; i < output_states_vect.length (); i++)
7671 state_t s = output_states_vect[i];
7672 size_t np = s->order_state_num
7673 * automaton->insn_equiv_classes_num
7674 + ainsn->insn_equiv_class_num;
7675 vect_el_t x = min_issue_delay_vect[np];
7677 if (automaton->max_min_delay < x)
7678 automaton->max_min_delay = x;
7679 if (x == -1)
7680 min_issue_delay_vect[np] = (vect_el_t) 0;
7684 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7685 fprintf (output_file, "static const ");
7686 output_range_type (output_file, 0, automaton->max_min_delay);
7687 fprintf (output_file, " ");
7688 output_min_issue_delay_vect_name (output_file, automaton);
7689 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7690 /* Compress the vector. */
7691 if (automaton->max_min_delay < 2)
7692 cfactor = 8;
7693 else if (automaton->max_min_delay < 4)
7694 cfactor = 4;
7695 else if (automaton->max_min_delay < 16)
7696 cfactor = 2;
7697 else
7698 cfactor = 1;
7699 automaton->min_issue_delay_table_compression_factor = cfactor;
7701 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7702 compressed_min_issue_delay_vect.create (compressed_min_issue_delay_len);
7704 for (i = 0; i < compressed_min_issue_delay_len; i++)
7705 compressed_min_issue_delay_vect.quick_push (0);
7707 for (i = 0; i < min_issue_delay_len; i++)
7709 size_t ci = i / cfactor;
7710 vect_el_t x = min_issue_delay_vect[i];
7711 vect_el_t cx = compressed_min_issue_delay_vect[ci];
7713 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7714 compressed_min_issue_delay_vect[ci] = cx;
7716 output_vect (compressed_min_issue_delay_vect);
7717 fprintf (output_file, "};\n\n");
7718 output_states_vect.release ();
7719 min_issue_delay_vect.release ();
7720 compressed_min_issue_delay_vect.release ();
7723 /* Form and output vector representing the locked states of
7724 AUTOMATON. */
7725 static void
7726 output_dead_lock_vect (automaton_t automaton)
7728 size_t i;
7729 arc_t arc;
7730 vla_hwint_t dead_lock_vect = vla_hwint_t ();
7732 /* Create vect of pointers to states ordered by num of
7733 transitions from the state (state with the maximum num is the
7734 first). */
7735 automaton->locked_states = 0;
7736 output_states_vect.create (0);
7737 pass_states (automaton, add_states_vect_el);
7739 dead_lock_vect.safe_grow (output_states_vect.length ());
7740 for (i = 0; i < output_states_vect.length (); i++)
7742 state_t s = output_states_vect[i];
7743 arc = first_out_arc (s);
7744 gcc_assert (arc);
7745 if (next_out_arc (arc) == NULL
7746 && (arc->insn->insn_reserv_decl
7747 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7749 dead_lock_vect[s->order_state_num] = 1;
7750 automaton->locked_states++;
7752 else
7753 dead_lock_vect[s->order_state_num] = (vect_el_t) 0;
7755 if (automaton->locked_states == 0)
7756 return;
7758 fprintf (output_file, "/* Vector for locked state flags. */\n");
7759 fprintf (output_file, "static const ");
7760 output_range_type (output_file, 0, 1);
7761 fprintf (output_file, " ");
7762 output_dead_lock_vect_name (output_file, automaton);
7763 fprintf (output_file, "[] = {\n");
7764 output_vect (dead_lock_vect);
7765 fprintf (output_file, "};\n\n");
7766 output_states_vect.release ();
7767 dead_lock_vect.release ();
7770 /* Form and output vector representing reserved units of the states of
7771 AUTOMATON. */
7772 static void
7773 output_reserved_units_table (automaton_t automaton)
7775 vla_hwint_t reserved_units_table = vla_hwint_t ();
7776 int state_byte_size;
7777 int reserved_units_size;
7778 size_t n;
7779 int i;
7781 if (description->query_units_num == 0)
7782 return;
7784 /* Create vect of pointers to states. */
7785 output_states_vect.create (0);
7786 pass_states (automaton, add_states_vect_el);
7787 /* Create vector. */
7788 state_byte_size = (description->query_units_num + 7) / 8;
7789 reserved_units_size = (output_states_vect.length ()
7790 * state_byte_size);
7792 reserved_units_table.create (reserved_units_size);
7794 for (i = 0; i < reserved_units_size; i++)
7795 reserved_units_table.quick_push (0);
7796 for (n = 0; n < output_states_vect.length (); n++)
7798 state_t s = output_states_vect[n];
7799 for (i = 0; i < description->units_num; i++)
7800 if (units_array [i]->query_p
7801 && first_cycle_unit_presence (s, i))
7803 int ri = (s->order_state_num * state_byte_size
7804 + units_array [i]->query_num / 8);
7805 vect_el_t x = reserved_units_table[ri];
7807 x += 1 << (units_array [i]->query_num % 8);
7808 reserved_units_table[ri] = x;
7811 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7812 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7813 fprintf (output_file, "static const ");
7814 output_range_type (output_file, 0, 255);
7815 fprintf (output_file, " ");
7816 output_reserved_units_table_name (output_file, automaton);
7817 fprintf (output_file, "[] = {\n");
7818 output_vect (reserved_units_table);
7819 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7820 CPU_UNITS_QUERY_MACRO_NAME);
7822 output_states_vect.release ();
7823 reserved_units_table.release ();
7826 /* The function outputs all tables representing DFA(s) used for fast
7827 pipeline hazards recognition. */
7828 static void
7829 output_tables (void)
7831 automaton_t automaton;
7833 for (automaton = description->first_automaton;
7834 automaton != NULL;
7835 automaton = automaton->next_automaton)
7837 output_translate_vect (automaton);
7838 output_trans_table (automaton);
7839 output_min_issue_delay_table (automaton);
7840 output_dead_lock_vect (automaton);
7841 output_reserved_units_table (automaton);
7843 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7844 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7845 if (collapse_flag)
7846 fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
7847 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
7850 /* The function outputs definition and value of PHR interface variable
7851 `max_insn_queue_index'. Its value is not less than maximal queue
7852 length needed for the insn scheduler. */
7853 static void
7854 output_max_insn_queue_index_def (void)
7856 int i, max, latency;
7857 decl_t decl;
7859 max = description->max_insn_reserv_cycles;
7860 for (i = 0; i < description->decls_num; i++)
7862 decl = description->decls [i];
7863 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7865 latency = DECL_INSN_RESERV (decl)->default_latency;
7866 if (latency > max)
7867 max = latency;
7869 else if (decl->mode == dm_bypass)
7871 latency = DECL_BYPASS (decl)->latency;
7872 if (latency > max)
7873 max = latency;
7876 for (i = 0; (1 << i) <= max; i++)
7878 gcc_assert (i >= 0);
7879 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7880 (1 << i) - 1);
7883 /* The function outputs switch cases for insn reservations using
7884 function *output_automata_list_code. */
7885 static void
7886 output_insn_code_cases (void (*output_automata_list_code)
7887 (automata_list_el_t))
7889 decl_t decl, decl2;
7890 int i, j;
7892 for (i = 0; i < description->decls_num; i++)
7894 decl = description->decls [i];
7895 if (decl->mode == dm_insn_reserv)
7896 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7898 for (i = 0; i < description->decls_num; i++)
7900 decl = description->decls [i];
7901 if (decl->mode == dm_insn_reserv
7902 && !DECL_INSN_RESERV (decl)->processed_p)
7904 for (j = i; j < description->decls_num; j++)
7906 decl2 = description->decls [j];
7907 if (decl2->mode == dm_insn_reserv
7908 && (DECL_INSN_RESERV (decl2)->important_automata_list
7909 == DECL_INSN_RESERV (decl)->important_automata_list))
7911 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7912 fprintf (output_file, " case %d: /* %s */\n",
7913 DECL_INSN_RESERV (decl2)->insn_num,
7914 DECL_INSN_RESERV (decl2)->name);
7917 (*output_automata_list_code)
7918 (DECL_INSN_RESERV (decl)->important_automata_list);
7924 /* The function outputs a code for evaluation of a minimal delay of
7925 issue of insns which have reservations in given AUTOMATA_LIST. */
7926 static void
7927 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7929 automata_list_el_t el;
7930 automaton_t automaton;
7932 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7934 automaton = el->automaton;
7935 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7936 output_min_issue_delay_vect_name (output_file, automaton);
7937 fprintf (output_file,
7938 (automaton->min_issue_delay_table_compression_factor != 1
7939 ? " [(" : " ["));
7940 output_translate_vect_name (output_file, automaton);
7941 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7942 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7943 output_chip_member_name (output_file, automaton);
7944 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7945 if (automaton->min_issue_delay_table_compression_factor == 1)
7946 fprintf (output_file, "];\n");
7947 else
7949 fprintf (output_file, ") / %d];\n",
7950 automaton->min_issue_delay_table_compression_factor);
7951 fprintf (output_file, " %s = (%s >> (8 - ((",
7952 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7953 output_translate_vect_name (output_file, automaton);
7954 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7955 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7956 output_chip_member_name (output_file, automaton);
7957 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7958 fprintf
7959 (output_file, " %% %d + 1) * %d)) & %d;\n",
7960 automaton->min_issue_delay_table_compression_factor,
7961 8 / automaton->min_issue_delay_table_compression_factor,
7962 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7963 - 1);
7965 if (el == automata_list)
7966 fprintf (output_file, " %s = %s;\n",
7967 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7968 else
7970 fprintf (output_file, " if (%s > %s)\n",
7971 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7972 fprintf (output_file, " %s = %s;\n",
7973 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7976 fprintf (output_file, " break;\n\n");
7979 /* Output function `internal_min_issue_delay'. */
7980 static void
7981 output_internal_min_issue_delay_func (void)
7983 fprintf (output_file,
7984 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7985 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7986 CHIP_NAME, CHIP_PARAMETER_NAME);
7987 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7988 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7989 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7990 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7991 fprintf (output_file,
7992 "\n default:\n %s = -1;\n break;\n }\n",
7993 RESULT_VARIABLE_NAME);
7994 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7995 fprintf (output_file, "}\n\n");
7998 /* The function outputs a code changing state after issue of insns
7999 which have reservations in given AUTOMATA_LIST. */
8000 static void
8001 output_automata_list_transition_code (automata_list_el_t automata_list)
8003 automata_list_el_t el, next_el;
8005 fprintf (output_file, " {\n");
8006 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8007 for (el = automata_list;; el = next_el)
8009 next_el = el->next_automata_list_el;
8010 if (next_el == NULL)
8011 break;
8012 fprintf (output_file, " ");
8013 output_state_member_type (output_file, el->automaton);
8014 fprintf (output_file, " ");
8015 output_temp_chip_member_name (output_file, el->automaton);
8016 fprintf (output_file, ";\n");
8018 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8019 if (comb_vect_p (el->automaton->trans_table))
8021 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8022 output_trans_base_vect_name (output_file, el->automaton);
8023 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8024 output_chip_member_name (output_file, el->automaton);
8025 fprintf (output_file, "] + ");
8026 output_translate_vect_name (output_file, el->automaton);
8027 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8028 fprintf (output_file, " if (");
8029 output_trans_check_vect_name (output_file, el->automaton);
8030 fprintf (output_file, " [%s] != %s->",
8031 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8032 output_chip_member_name (output_file, el->automaton);
8033 fprintf (output_file, ")\n");
8034 fprintf (output_file, " return %s (%s, %s);\n",
8035 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8036 CHIP_PARAMETER_NAME);
8037 fprintf (output_file, " else\n");
8038 fprintf (output_file, " ");
8039 if (el->next_automata_list_el != NULL)
8040 output_temp_chip_member_name (output_file, el->automaton);
8041 else
8043 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8044 output_chip_member_name (output_file, el->automaton);
8046 fprintf (output_file, " = ");
8047 output_trans_comb_vect_name (output_file, el->automaton);
8048 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8050 else
8052 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8053 output_trans_full_vect_name (output_file, el->automaton);
8054 fprintf (output_file, " [");
8055 output_translate_vect_name (output_file, el->automaton);
8056 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8057 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8058 output_chip_member_name (output_file, el->automaton);
8059 fprintf (output_file, " * %d];\n",
8060 el->automaton->insn_equiv_classes_num);
8061 fprintf (output_file, " if (%s >= %d)\n",
8062 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8063 fprintf (output_file, " return %s (%s, %s);\n",
8064 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8065 CHIP_PARAMETER_NAME);
8066 fprintf (output_file, " else\n ");
8067 if (el->next_automata_list_el != NULL)
8068 output_temp_chip_member_name (output_file, el->automaton);
8069 else
8071 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8072 output_chip_member_name (output_file, el->automaton);
8074 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8076 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8077 for (el = automata_list;; el = next_el)
8079 next_el = el->next_automata_list_el;
8080 if (next_el == NULL)
8081 break;
8082 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8083 output_chip_member_name (output_file, el->automaton);
8084 fprintf (output_file, " = ");
8085 output_temp_chip_member_name (output_file, el->automaton);
8086 fprintf (output_file, ";\n");
8088 fprintf (output_file, " return -1;\n");
8089 fprintf (output_file, " }\n");
8092 /* Output function `internal_state_transition'. */
8093 static void
8094 output_internal_trans_func (void)
8096 fprintf (output_file,
8097 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8098 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8099 CHIP_NAME, CHIP_PARAMETER_NAME);
8100 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8101 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8102 output_insn_code_cases (output_automata_list_transition_code);
8103 fprintf (output_file, "\n default:\n return -1;\n }\n");
8104 fprintf (output_file, "}\n\n");
8107 /* Output code
8109 if (insn != 0)
8111 insn_code = dfa_insn_code (insn);
8112 if (insn_code > DFA__ADVANCE_CYCLE)
8113 return code;
8115 else
8116 insn_code = DFA__ADVANCE_CYCLE;
8118 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8119 code denotes CODE. */
8120 static void
8121 output_internal_insn_code_evaluation (const char *insn_name,
8122 const char *insn_code_name,
8123 int code)
8125 fprintf (output_file, "\n if (%s == 0)\n", insn_name);
8126 fprintf (output_file, " %s = %s;\n\n",
8127 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8128 if (collapse_flag)
8130 fprintf (output_file, "\n else if (%s == const0_rtx)\n", insn_name);
8131 fprintf (output_file, " %s = %s;\n\n",
8132 insn_code_name, COLLAPSE_NDFA_VALUE_NAME);
8134 fprintf (output_file, "\n else\n {\n");
8135 fprintf (output_file,
8136 " %s = %s (as_a <rtx_insn *> (%s));\n",
8137 insn_code_name, DFA_INSN_CODE_FUNC_NAME, insn_name);
8138 fprintf (output_file, " if (%s > %s)\n return %d;\n }\n",
8139 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8143 /* This function outputs `dfa_insn_code' and its helper function
8144 `dfa_insn_code_enlarge'. */
8145 static void
8146 output_dfa_insn_code_func (void)
8148 /* Emacs c-mode gets really confused if there's a { or } in column 0
8149 inside a string, so don't do that. */
8150 fprintf (output_file, "\
8151 static void\n\
8152 dfa_insn_code_enlarge (int uid)\n\
8153 {\n\
8154 int i = %s;\n\
8155 %s = 2 * uid;\n\
8156 %s = XRESIZEVEC (int, %s,\n\
8157 %s);\n\
8158 for (; i < %s; i++)\n\
8159 %s[i] = -1;\n}\n\n",
8160 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8161 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8162 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8163 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8164 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8165 DFA_INSN_CODES_VARIABLE_NAME);
8166 fprintf (output_file, "\
8167 static inline int\n%s (rtx_insn *%s)\n\
8168 {\n\
8169 int uid = INSN_UID (%s);\n\
8170 int %s;\n\n",
8171 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8172 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8174 fprintf (output_file,
8175 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8176 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8177 fprintf (output_file, " %s = %s[uid];\n",
8178 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8179 fprintf (output_file, "\
8180 if (%s < 0)\n\
8181 {\n\
8182 %s = %s (%s);\n\
8183 %s[uid] = %s;\n\
8184 }\n",
8185 INTERNAL_INSN_CODE_NAME,
8186 INTERNAL_INSN_CODE_NAME,
8187 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8188 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8189 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8192 /* The function outputs PHR interface function `state_transition'. */
8193 static void
8194 output_trans_func (void)
8196 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8197 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8198 INSN_PARAMETER_NAME);
8199 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8200 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8201 INTERNAL_INSN_CODE_NAME, -1);
8202 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8203 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8206 /* Output function `min_issue_delay'. */
8207 static void
8208 output_min_issue_delay_func (void)
8210 fprintf (output_file, "int\n%s (%s %s, rtx_insn *%s)\n",
8211 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8212 INSN_PARAMETER_NAME);
8213 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8214 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8215 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8216 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8217 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8218 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8219 fprintf (output_file, " }\n else\n %s = %s;\n",
8220 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8221 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8222 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8223 CHIP_NAME, STATE_NAME);
8224 fprintf (output_file, "}\n\n");
8227 /* Output function `internal_dead_lock'. */
8228 static void
8229 output_internal_dead_lock_func (void)
8231 automaton_t automaton;
8233 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8234 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8235 fprintf (output_file, "{\n");
8236 for (automaton = description->first_automaton;
8237 automaton != NULL;
8238 automaton = automaton->next_automaton)
8239 if (automaton->locked_states)
8241 fprintf (output_file, " if (");
8242 output_dead_lock_vect_name (output_file, automaton);
8243 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8244 output_chip_member_name (output_file, automaton);
8245 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8247 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8250 /* The function outputs PHR interface function `state_dead_lock_p'. */
8251 static void
8252 output_dead_lock_func (void)
8254 fprintf (output_file, "int\n%s (%s %s)\n",
8255 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8256 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8257 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8260 /* Output function `internal_reset'. */
8261 static void
8262 output_internal_reset_func (void)
8264 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8265 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8266 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8267 CHIP_PARAMETER_NAME, CHIP_NAME);
8270 /* The function outputs PHR interface function `state_size'. */
8271 static void
8272 output_size_func (void)
8274 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8275 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8278 /* The function outputs PHR interface function `state_reset'. */
8279 static void
8280 output_reset_func (void)
8282 fprintf (output_file, "void\n%s (%s %s)\n",
8283 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8284 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8285 CHIP_NAME, STATE_NAME);
8288 /* Output function `min_insn_conflict_delay'. */
8289 static void
8290 output_min_insn_conflict_delay_func (void)
8292 fprintf (output_file,
8293 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8294 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8295 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8296 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8297 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8298 INTERNAL_INSN2_CODE_NAME);
8299 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8300 INTERNAL_INSN_CODE_NAME, 0);
8301 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8302 INTERNAL_INSN2_CODE_NAME, 0);
8303 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8304 CHIP_NAME, STATE_NAME, CHIP_NAME);
8305 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8306 fprintf (output_file, " transition = %s (%s, &%s);\n",
8307 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8308 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8309 fprintf (output_file, " return %s (%s, &%s);\n",
8310 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8311 CHIP_NAME);
8312 fprintf (output_file, "}\n\n");
8315 /* Output the array holding default latency values. These are used in
8316 insn_latency and maximal_insn_latency function implementations. */
8317 static void
8318 output_default_latencies (void)
8320 int i, j, col;
8321 decl_t decl;
8322 const char *tabletype = "unsigned char";
8324 /* Find the smallest integer type that can hold all the default
8325 latency values. */
8326 for (i = 0; i < description->decls_num; i++)
8327 if (description->decls[i]->mode == dm_insn_reserv)
8329 decl = description->decls[i];
8330 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8331 && tabletype[0] != 'i') /* Don't shrink it. */
8332 tabletype = "unsigned short";
8333 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8334 tabletype = "int";
8337 fprintf (output_file, " static const %s default_latencies[] =\n {",
8338 tabletype);
8340 for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
8341 if (description->decls[i]->mode == dm_insn_reserv)
8343 if ((col = (col+1) % 8) == 0)
8344 fputs ("\n ", output_file);
8345 decl = description->decls[i];
8346 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8347 fprintf (output_file, "% 4d,",
8348 DECL_INSN_RESERV (decl)->default_latency);
8350 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8351 fputs ("\n };\n", output_file);
8354 /* Output function `internal_insn_latency'. */
8355 static void
8356 output_internal_insn_latency_func (void)
8358 int i;
8359 decl_t decl;
8360 struct bypass_decl *bypass;
8362 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",
8363 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8364 INTERNAL_INSN2_CODE_NAME, "insn_or_const0",
8365 "insn2_or_const0");
8366 fprintf (output_file, "{\n");
8368 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8370 fputs (" return 0;\n}\n\n", output_file);
8371 return;
8374 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8375 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8376 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8378 /* We've now rejected the case that
8379 INTERNAL_INSN_CODE_NAME >= ADVANCE_CYCLE_VALUE_NAME
8380 i.e. that
8381 insn_code >= DFA__ADVANCE_CYCLE,
8382 and similarly for insn2_code. */
8383 fprintf (output_file,
8384 " /* Within output_internal_insn_code_evaluation, the generated\n"
8385 " code sets \"code\" to NDFA__COLLAPSE for const0_rtx, and\n"
8386 " NDFA__COLLAPSE > DFA__ADVANCE_CYCLE. Hence we can't be\n"
8387 " dealing with const0_rtx instances at this point. */\n");
8388 if (collapse_flag)
8389 fprintf (output_file,
8390 " gcc_assert (NDFA__COLLAPSE > DFA__ADVANCE_CYCLE);\n");
8391 fprintf (output_file,
8392 (" gcc_assert (insn_or_const0 != const0_rtx);\n"
8393 " rtx_insn *%s ATTRIBUTE_UNUSED = safe_as_a <rtx_insn *> (insn_or_const0);\n"),
8394 INSN_PARAMETER_NAME);
8395 fprintf (output_file,
8396 (" gcc_assert (insn2_or_const0 != const0_rtx);\n"
8397 " rtx_insn *%s ATTRIBUTE_UNUSED = safe_as_a <rtx_insn *> (insn2_or_const0);\n"),
8398 INSN2_PARAMETER_NAME);
8400 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8401 for (i = 0; i < description->decls_num; i++)
8402 if (description->decls[i]->mode == dm_insn_reserv
8403 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8405 decl = description->decls [i];
8406 fprintf (output_file,
8407 " case %d:\n switch (%s)\n {\n",
8408 DECL_INSN_RESERV (decl)->insn_num,
8409 INTERNAL_INSN2_CODE_NAME);
8410 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8411 bypass != NULL;
8412 bypass = bypass->next)
8414 gcc_assert (bypass->in_insn_reserv->insn_num
8415 != (DECL_INSN_RESERV
8416 (advance_cycle_insn_decl)->insn_num));
8417 fprintf (output_file, " case %d:\n",
8418 bypass->in_insn_reserv->insn_num);
8419 for (;;)
8421 if (bypass->bypass_guard_name == NULL)
8423 gcc_assert (bypass->next == NULL
8424 || (bypass->in_insn_reserv
8425 != bypass->next->in_insn_reserv));
8426 fprintf (output_file, " return %d;\n",
8427 bypass->latency);
8429 else
8431 fprintf (output_file,
8432 " if (%s (%s, %s))\n",
8433 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8434 INSN2_PARAMETER_NAME);
8435 fprintf (output_file, " return %d;\n",
8436 bypass->latency);
8438 if (bypass->next == NULL
8439 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8440 break;
8441 bypass = bypass->next;
8443 if (bypass->bypass_guard_name != NULL)
8444 fprintf (output_file, " break;\n");
8446 fputs (" }\n break;\n", output_file);
8449 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8450 INTERNAL_INSN_CODE_NAME);
8453 /* Output function `internal_maximum_insn_latency'. */
8454 static void
8455 output_internal_maximal_insn_latency_func (void)
8457 decl_t decl;
8458 struct bypass_decl *bypass;
8459 int i;
8460 int max;
8462 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8463 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8464 INSN_PARAMETER_NAME);
8465 fprintf (output_file, "{\n");
8467 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8469 fputs (" return 0;\n}\n\n", output_file);
8470 return;
8473 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8474 for (i = 0; i < description->decls_num; i++)
8475 if (description->decls[i]->mode == dm_insn_reserv
8476 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8478 decl = description->decls [i];
8479 max = DECL_INSN_RESERV (decl)->default_latency;
8480 fprintf (output_file,
8481 " case %d: {",
8482 DECL_INSN_RESERV (decl)->insn_num);
8483 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8484 bypass != NULL;
8485 bypass = bypass->next)
8487 if (bypass->latency > max)
8488 max = bypass->latency;
8490 fprintf (output_file, " return %d; }\n break;\n", max);
8493 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8494 INTERNAL_INSN_CODE_NAME);
8497 /* The function outputs PHR interface function `insn_latency'. */
8498 static void
8499 output_insn_latency_func (void)
8501 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8502 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8503 fprintf (output_file, "{\n int %s, %s;\n",
8504 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8505 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8506 INTERNAL_INSN_CODE_NAME, 0);
8507 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8508 INTERNAL_INSN2_CODE_NAME, 0);
8509 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8510 INTERNAL_INSN_LATENCY_FUNC_NAME,
8511 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8512 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8515 /* The function outputs PHR interface function `maximal_insn_latency'. */
8516 static void
8517 output_maximal_insn_latency_func (void)
8519 fprintf (output_file, "int\n%s (rtx %s)\n",
8520 "maximal_insn_latency", INSN_PARAMETER_NAME);
8521 fprintf (output_file, "{\n int %s;\n",
8522 INTERNAL_INSN_CODE_NAME);
8523 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8524 INTERNAL_INSN_CODE_NAME, 0);
8525 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8526 "internal_maximal_insn_latency",
8527 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8530 /* The function outputs PHR interface function `print_reservation'. */
8531 static void
8532 output_print_reservation_func (void)
8534 decl_t decl;
8535 int i, j;
8537 fprintf (output_file,
8538 "void\n%s (FILE *%s, rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8539 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8540 INSN_PARAMETER_NAME);
8542 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8544 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8545 NOTHING_NAME, FILE_PARAMETER_NAME);
8546 return;
8550 fputs (" static const char *const reservation_names[] =\n {",
8551 output_file);
8553 for (i = 0, j = 0; i < description->normal_decls_num; i++)
8555 decl = description->decls [i];
8556 if (decl->mode == dm_insn_reserv)
8558 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8559 j++;
8561 fprintf (output_file, "\n \"%s\",",
8562 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8563 finish_regexp_representation ();
8566 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8568 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8569 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8571 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8572 INSN_PARAMETER_NAME,
8573 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8574 fprintf (output_file, " else\n\
8575 {\n\
8576 %s = %s (%s);\n\
8577 if (%s > %s)\n\
8578 %s = %s;\n\
8579 }\n",
8580 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8581 INSN_PARAMETER_NAME,
8582 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8583 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8585 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8586 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8589 /* The following function is used to sort unit declaration by their
8590 names. */
8591 static int
8592 units_cmp (const void *unit1, const void *unit2)
8594 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8595 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8597 return strcmp (u1->name, u2->name);
8600 /* The following macro value is name of struct containing unit name
8601 and unit code. */
8602 #define NAME_CODE_STRUCT_NAME "name_code"
8604 /* The following macro value is name of table of struct name_code. */
8605 #define NAME_CODE_TABLE_NAME "name_code_table"
8607 /* The following macro values are member names for struct name_code. */
8608 #define NAME_MEMBER_NAME "name"
8609 #define CODE_MEMBER_NAME "code"
8611 /* The following macro values are local variable names for function
8612 `get_cpu_unit_code'. */
8613 #define CMP_VARIABLE_NAME "cmp"
8614 #define LOW_VARIABLE_NAME "l"
8615 #define MIDDLE_VARIABLE_NAME "m"
8616 #define HIGH_VARIABLE_NAME "h"
8618 /* The following function outputs function to obtain internal cpu unit
8619 code by the cpu unit name. */
8620 static void
8621 output_get_cpu_unit_code_func (void)
8623 int i;
8624 unit_decl_t *units;
8626 fprintf (output_file, "int\n%s (const char *%s)\n",
8627 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8628 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8629 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8630 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8631 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8632 fprintf (output_file, " static struct %s %s [] =\n {\n",
8633 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8634 units = XNEWVEC (unit_decl_t, description->units_num);
8635 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8636 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8637 for (i = 0; i < description->units_num; i++)
8638 if (units [i]->query_p)
8639 fprintf (output_file, " {\"%s\", %d},\n",
8640 units[i]->name, units[i]->query_num);
8641 fprintf (output_file, " };\n\n");
8642 fprintf (output_file, " /* The following is binary search: */\n");
8643 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8644 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8645 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8646 fprintf (output_file, " while (%s <= %s)\n {\n",
8647 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8648 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8649 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8650 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8651 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8652 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8653 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8654 fprintf (output_file, " %s = %s - 1;\n",
8655 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8656 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8657 fprintf (output_file, " %s = %s + 1;\n",
8658 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8659 fprintf (output_file, " else\n");
8660 fprintf (output_file, " return %s [%s].%s;\n }\n",
8661 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8662 fprintf (output_file, " return -1;\n}\n\n");
8663 free (units);
8666 /* The following function outputs function to check reservation of cpu
8667 unit (its internal code will be passed as the function argument) in
8668 given cpu state. */
8669 static void
8670 output_cpu_unit_reservation_p (void)
8672 automaton_t automaton;
8674 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8675 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8676 STATE_TYPE_NAME, STATE_NAME,
8677 CPU_CODE_PARAMETER_NAME);
8678 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8679 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8680 description->query_units_num);
8681 if (description->query_units_num > 0)
8682 for (automaton = description->first_automaton;
8683 automaton != NULL;
8684 automaton = automaton->next_automaton)
8686 fprintf (output_file, " if ((");
8687 output_reserved_units_table_name (output_file, automaton);
8688 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8689 output_chip_member_name (output_file, automaton);
8690 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8691 (description->query_units_num + 7) / 8,
8692 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8693 fprintf (output_file, " return 1;\n");
8695 fprintf (output_file, " return 0;\n}\n\n");
8698 /* The following function outputs a function to check if insn
8699 has a dfa reservation. */
8700 static void
8701 output_insn_has_dfa_reservation_p (void)
8703 fprintf (output_file,
8704 "bool\n%s (rtx_insn *%s ATTRIBUTE_UNUSED)\n{\n",
8705 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8706 INSN_PARAMETER_NAME);
8708 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8710 fprintf (output_file, " return false;\n}\n\n");
8711 return;
8714 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8716 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8717 INSN_PARAMETER_NAME,
8718 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8719 fprintf (output_file, " else\n\
8720 {\n\
8721 %s = %s (%s);\n\
8722 if (%s > %s)\n\
8723 %s = %s;\n\
8724 }\n\n",
8725 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8726 INSN_PARAMETER_NAME,
8727 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8728 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8730 fprintf (output_file, " return %s != %s;\n}\n\n",
8731 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8734 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8735 and 'dfa_clear_single_insn_cache'. */
8736 static void
8737 output_dfa_clean_insn_cache_func (void)
8739 fprintf (output_file,
8740 "void\n%s (void)\n{\n int %s;\n\n",
8741 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8742 fprintf (output_file,
8743 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8744 I_VARIABLE_NAME, I_VARIABLE_NAME,
8745 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8746 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8748 fprintf (output_file,
8749 "void\n%s (rtx_insn *%s)\n{\n int %s;\n\n",
8750 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8751 I_VARIABLE_NAME);
8752 fprintf (output_file,
8753 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8754 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8755 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8756 I_VARIABLE_NAME);
8759 /* The function outputs PHR interface function `dfa_start'. */
8760 static void
8761 output_dfa_start_func (void)
8763 fprintf (output_file,
8764 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8765 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8766 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8767 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8768 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8771 /* The function outputs PHR interface function `dfa_finish'. */
8772 static void
8773 output_dfa_finish_func (void)
8775 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8776 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8781 /* The page contains code for output description file (readable
8782 representation of original description and generated DFA(s). */
8784 /* The function outputs string representation of IR reservation. */
8785 static void
8786 output_regexp (regexp_t regexp)
8788 fprintf (output_description_file, "%s", regexp_representation (regexp));
8789 finish_regexp_representation ();
8792 /* Output names of units in LIST separated by comma. */
8793 static void
8794 output_unit_set_el_list (unit_set_el_t list)
8796 unit_set_el_t el;
8798 for (el = list; el != NULL; el = el->next_unit_set_el)
8800 if (el != list)
8801 fprintf (output_description_file, ", ");
8802 fprintf (output_description_file, "%s", el->unit_decl->name);
8806 /* Output patterns in LIST separated by comma. */
8807 static void
8808 output_pattern_set_el_list (pattern_set_el_t list)
8810 pattern_set_el_t el;
8811 int i;
8813 for (el = list; el != NULL; el = el->next_pattern_set_el)
8815 if (el != list)
8816 fprintf (output_description_file, ", ");
8817 for (i = 0; i < el->units_num; i++)
8818 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8819 el->unit_decls [i]->name);
8823 /* The function outputs string representation of IR define_reservation
8824 and define_insn_reservation. */
8825 static void
8826 output_description (void)
8828 decl_t decl;
8829 int i;
8831 for (i = 0; i < description->decls_num; i++)
8833 decl = description->decls [i];
8834 if (decl->mode == dm_unit)
8836 if (DECL_UNIT (decl)->excl_list != NULL)
8838 fprintf (output_description_file, "unit %s exclusion_set: ",
8839 DECL_UNIT (decl)->name);
8840 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8841 fprintf (output_description_file, "\n");
8843 if (DECL_UNIT (decl)->presence_list != NULL)
8845 fprintf (output_description_file, "unit %s presence_set: ",
8846 DECL_UNIT (decl)->name);
8847 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8848 fprintf (output_description_file, "\n");
8850 if (DECL_UNIT (decl)->final_presence_list != NULL)
8852 fprintf (output_description_file, "unit %s final_presence_set: ",
8853 DECL_UNIT (decl)->name);
8854 output_pattern_set_el_list
8855 (DECL_UNIT (decl)->final_presence_list);
8856 fprintf (output_description_file, "\n");
8858 if (DECL_UNIT (decl)->absence_list != NULL)
8860 fprintf (output_description_file, "unit %s absence_set: ",
8861 DECL_UNIT (decl)->name);
8862 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8863 fprintf (output_description_file, "\n");
8865 if (DECL_UNIT (decl)->final_absence_list != NULL)
8867 fprintf (output_description_file, "unit %s final_absence_set: ",
8868 DECL_UNIT (decl)->name);
8869 output_pattern_set_el_list
8870 (DECL_UNIT (decl)->final_absence_list);
8871 fprintf (output_description_file, "\n");
8875 fprintf (output_description_file, "\n");
8876 for (i = 0; i < description->normal_decls_num; i++)
8878 decl = description->decls [i];
8879 if (decl->mode == dm_reserv)
8881 fprintf (output_description_file, "reservation %s: ",
8882 DECL_RESERV (decl)->name);
8883 output_regexp (DECL_RESERV (decl)->regexp);
8884 fprintf (output_description_file, "\n");
8886 else if (decl->mode == dm_insn_reserv)
8888 fprintf (output_description_file, "insn reservation %s ",
8889 DECL_INSN_RESERV (decl)->name);
8890 print_rtl (output_description_file,
8891 DECL_INSN_RESERV (decl)->condexp);
8892 fprintf (output_description_file, ": ");
8893 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8894 fprintf (output_description_file, "\n");
8896 else if (decl->mode == dm_bypass)
8897 fprintf (output_description_file, "bypass %d %s %s\n",
8898 DECL_BYPASS (decl)->latency,
8899 DECL_BYPASS (decl)->out_pattern,
8900 DECL_BYPASS (decl)->in_pattern);
8902 fprintf (output_description_file, "\n\f\n");
8905 /* The function outputs name of AUTOMATON. */
8906 static void
8907 output_automaton_name (FILE *f, automaton_t automaton)
8909 if (automaton->corresponding_automaton_decl == NULL)
8910 fprintf (f, "#%d", automaton->automaton_order_num);
8911 else
8912 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8915 /* Maximal length of line for pretty printing into description
8916 file. */
8917 #define MAX_LINE_LENGTH 70
8919 /* The function outputs units name belonging to AUTOMATON. */
8920 static void
8921 output_automaton_units (automaton_t automaton)
8923 decl_t decl;
8924 const char *name;
8925 int curr_line_length;
8926 int there_is_an_automaton_unit;
8927 int i;
8929 fprintf (output_description_file, "\n Corresponding units:\n");
8930 fprintf (output_description_file, " ");
8931 curr_line_length = 4;
8932 there_is_an_automaton_unit = 0;
8933 for (i = 0; i < description->decls_num; i++)
8935 decl = description->decls [i];
8936 if (decl->mode == dm_unit
8937 && (DECL_UNIT (decl)->corresponding_automaton_num
8938 == automaton->automaton_order_num))
8940 there_is_an_automaton_unit = 1;
8941 name = DECL_UNIT (decl)->name;
8942 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8944 curr_line_length = strlen (name) + 4;
8945 fprintf (output_description_file, "\n ");
8947 else
8949 curr_line_length += strlen (name) + 1;
8950 fprintf (output_description_file, " ");
8952 fprintf (output_description_file, "%s", name);
8955 if (!there_is_an_automaton_unit)
8956 fprintf (output_description_file, "<None>");
8957 fprintf (output_description_file, "\n\n");
8960 /* The following variable is used for forming array of all possible cpu unit
8961 reservations described by the current DFA state. */
8962 static vec<reserv_sets_t> state_reservs;
8964 /* The function forms `state_reservs' for STATE. */
8965 static void
8966 add_state_reservs (state_t state)
8968 alt_state_t curr_alt_state;
8970 if (state->component_states != NULL)
8971 for (curr_alt_state = state->component_states;
8972 curr_alt_state != NULL;
8973 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8974 add_state_reservs (curr_alt_state->state);
8975 else
8976 state_reservs.safe_push (state->reservs);
8979 /* The function outputs readable representation of all out arcs of
8980 STATE. */
8981 static void
8982 output_state_arcs (state_t state)
8984 arc_t arc;
8985 ainsn_t ainsn;
8986 const char *insn_name;
8987 int curr_line_length;
8989 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8991 ainsn = arc->insn;
8992 gcc_assert (ainsn->first_insn_with_same_reservs);
8993 fprintf (output_description_file, " ");
8994 curr_line_length = 7;
8995 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8998 insn_name = ainsn->insn_reserv_decl->name;
8999 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9001 if (ainsn != arc->insn)
9003 fprintf (output_description_file, ",\n ");
9004 curr_line_length = strlen (insn_name) + 6;
9006 else
9007 curr_line_length += strlen (insn_name);
9009 else
9011 curr_line_length += strlen (insn_name);
9012 if (ainsn != arc->insn)
9014 curr_line_length += 2;
9015 fprintf (output_description_file, ", ");
9018 fprintf (output_description_file, "%s", insn_name);
9019 ainsn = ainsn->next_same_reservs_insn;
9021 while (ainsn != NULL);
9022 fprintf (output_description_file, " %d \n",
9023 arc->to_state->order_state_num);
9025 fprintf (output_description_file, "\n");
9028 /* The following function is used for sorting possible cpu unit
9029 reservation of a DFA state. */
9030 static int
9031 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9033 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
9034 *(const_reserv_sets_t const*) reservs_ptr_2);
9037 /* The following function is used for sorting possible cpu unit
9038 reservation of a DFA state. */
9039 static void
9040 remove_state_duplicate_reservs (void)
9042 size_t i, j;
9044 for (i = 1, j = 0; i < state_reservs.length (); i++)
9045 if (reserv_sets_cmp (state_reservs[j], state_reservs[i]))
9047 j++;
9048 state_reservs[j] = state_reservs[i];
9050 state_reservs.truncate (j + 1);
9053 /* The following function output readable representation of DFA(s)
9054 state used for fast recognition of pipeline hazards. State is
9055 described by possible (current and scheduled) cpu unit
9056 reservations. */
9057 static void
9058 output_state (state_t state)
9060 size_t i;
9062 state_reservs.create (0);
9064 fprintf (output_description_file, " State #%d", state->order_state_num);
9065 fprintf (output_description_file,
9066 state->new_cycle_p ? " (new cycle)\n" : "\n");
9067 add_state_reservs (state);
9068 state_reservs.qsort (state_reservs_cmp);
9069 remove_state_duplicate_reservs ();
9070 for (i = 0; i < state_reservs.length (); i++)
9072 fprintf (output_description_file, " ");
9073 output_reserv_sets (output_description_file, state_reservs[i]);
9074 fprintf (output_description_file, "\n");
9076 fprintf (output_description_file, "\n");
9077 output_state_arcs (state);
9078 state_reservs.release ();
9081 /* The following function output readable representation of
9082 DFAs used for fast recognition of pipeline hazards. */
9083 static void
9084 output_automaton_descriptions (void)
9086 automaton_t automaton;
9088 for (automaton = description->first_automaton;
9089 automaton != NULL;
9090 automaton = automaton->next_automaton)
9092 fprintf (output_description_file, "\nAutomaton ");
9093 output_automaton_name (output_description_file, automaton);
9094 fprintf (output_description_file, "\n");
9095 output_automaton_units (automaton);
9096 pass_states (automaton, output_state);
9102 /* The page contains top level function for generation DFA(s) used for
9103 PHR. */
9105 /* The function outputs statistics about work of different phases of
9106 DFA generator. */
9107 static void
9108 output_statistics (FILE *f)
9110 automaton_t automaton;
9111 int states_num;
9112 #ifndef NDEBUG
9113 int transition_comb_vect_els = 0;
9114 int transition_full_vect_els = 0;
9115 int min_issue_delay_vect_els = 0;
9116 int locked_states = 0;
9117 #endif
9119 for (automaton = description->first_automaton;
9120 automaton != NULL;
9121 automaton = automaton->next_automaton)
9123 fprintf (f, "\nAutomaton ");
9124 output_automaton_name (f, automaton);
9125 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9126 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9127 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9128 automaton->DFA_states_num, automaton->DFA_arcs_num);
9129 states_num = automaton->DFA_states_num;
9130 if (!no_minimization_flag)
9132 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9133 automaton->minimal_DFA_states_num,
9134 automaton->minimal_DFA_arcs_num);
9135 states_num = automaton->minimal_DFA_states_num;
9137 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9138 description->insns_num, automaton->insn_equiv_classes_num);
9139 fprintf (f, " %d locked states\n", automaton->locked_states);
9140 #ifndef NDEBUG
9141 fprintf
9142 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9143 (long) automaton->trans_table->comb_vect.length (),
9144 (long) automaton->trans_table->full_vect.length (),
9145 (comb_vect_p (automaton->trans_table)
9146 ? "use comb vect" : "use simple vect"));
9147 fprintf
9148 (f, "%5ld min delay table els, compression factor %d\n",
9149 (long) states_num * automaton->insn_equiv_classes_num,
9150 automaton->min_issue_delay_table_compression_factor);
9151 transition_comb_vect_els
9152 += automaton->trans_table->comb_vect.length ();
9153 transition_full_vect_els
9154 += automaton->trans_table->full_vect.length ();
9155 min_issue_delay_vect_els
9156 += states_num * automaton->insn_equiv_classes_num;
9157 locked_states
9158 += automaton->locked_states;
9159 #endif
9161 #ifndef NDEBUG
9162 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9163 allocated_states_num, allocated_arcs_num);
9164 fprintf (f, "%5d all allocated alternative states\n",
9165 allocated_alt_states_num);
9166 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9167 transition_comb_vect_els, transition_full_vect_els);
9168 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9169 fprintf (f, "%5d all locked states\n", locked_states);
9170 #endif
9173 /* The function output times of work of different phases of DFA
9174 generator. */
9175 static void
9176 output_time_statistics (FILE *f)
9178 fprintf (f, "\n transformation: ");
9179 print_active_time (f, transform_time);
9180 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9181 print_active_time (f, NDFA_time);
9182 if (ndfa_flag)
9184 fprintf (f, ", NDFA -> DFA: ");
9185 print_active_time (f, NDFA_to_DFA_time);
9187 fprintf (f, "\n DFA minimization: ");
9188 print_active_time (f, minimize_time);
9189 fprintf (f, ", making insn equivalence: ");
9190 print_active_time (f, equiv_time);
9191 fprintf (f, "\n all automaton generation: ");
9192 print_active_time (f, automaton_generation_time);
9193 fprintf (f, ", output: ");
9194 print_active_time (f, output_time);
9195 fprintf (f, "\n");
9198 /* The function generates DFA (deterministic finite state automaton)
9199 for fast recognition of pipeline hazards. No errors during
9200 checking must be fixed before this function call. */
9201 static void
9202 generate (void)
9204 automata_num = split_argument;
9205 if (description->units_num < automata_num)
9206 automata_num = description->units_num;
9207 initiate_states ();
9208 initiate_arcs ();
9209 initiate_automata_lists ();
9210 initiate_pass_states ();
9211 initiate_excl_sets ();
9212 initiate_presence_absence_pattern_sets ();
9213 automaton_generation_time = create_ticker ();
9214 create_automata ();
9215 ticker_off (&automaton_generation_time);
9220 /* This page mainly contains top level functions of pipeline hazards
9221 description translator. */
9223 /* The following macro value is suffix of name of description file of
9224 pipeline hazards description translator. */
9225 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9227 /* The function returns suffix of given file name. The returned
9228 string can not be changed. */
9229 static const char *
9230 file_name_suffix (const char *file_name)
9232 const char *last_period;
9234 for (last_period = NULL; *file_name != '\0'; file_name++)
9235 if (*file_name == '.')
9236 last_period = file_name;
9237 return (last_period == NULL ? file_name : last_period);
9240 /* The function returns base name of given file name, i.e. pointer to
9241 first char after last `/' (or `\' for WIN32) in given file name,
9242 given file name itself if the directory name is absent. The
9243 returned string can not be changed. */
9244 static const char *
9245 base_file_name (const char *file_name)
9247 int directory_name_length;
9249 directory_name_length = strlen (file_name);
9250 #ifdef WIN32
9251 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9252 && file_name[directory_name_length] != '\\')
9253 #else
9254 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9255 #endif
9256 directory_name_length--;
9257 return file_name + directory_name_length + 1;
9260 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9261 options available for genautomata. Returns true if the option was
9262 recognized. */
9263 static bool
9264 parse_automata_opt (const char *str)
9266 if (strcmp (str, NO_MINIMIZATION_OPTION) == 0)
9267 no_minimization_flag = 1;
9268 else if (strcmp (str, TIME_OPTION) == 0)
9269 time_flag = 1;
9270 else if (strcmp (str, STATS_OPTION) == 0)
9271 stats_flag = 1;
9272 else if (strcmp (str, V_OPTION) == 0)
9273 v_flag = 1;
9274 else if (strcmp (str, W_OPTION) == 0)
9275 w_flag = 1;
9276 else if (strcmp (str, NDFA_OPTION) == 0)
9277 ndfa_flag = 1;
9278 else if (strcmp (str, COLLAPSE_OPTION) == 0)
9279 collapse_flag = 1;
9280 else if (strcmp (str, PROGRESS_OPTION) == 0)
9281 progress_flag = 1;
9282 else if (strcmp (str, "-split") == 0)
9284 fatal ("option `-split' has not been implemented yet\n");
9285 /* split_argument = atoi (argument_vect [i + 1]); */
9287 else
9288 return false;
9290 return true;
9293 /* The following is top level function to initialize the work of
9294 pipeline hazards description translator. */
9295 static void
9296 initiate_automaton_gen (char **argv)
9298 const char *base_name;
9300 /* Initialize IR storage. */
9301 obstack_init (&irp);
9302 initiate_automaton_decl_table ();
9303 initiate_insn_decl_table ();
9304 initiate_decl_table ();
9305 output_file = stdout;
9306 output_description_file = NULL;
9307 base_name = base_file_name (argv[1]);
9308 obstack_grow (&irp, base_name,
9309 strlen (base_name) - strlen (file_name_suffix (base_name)));
9310 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9311 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9312 obstack_1grow (&irp, '\0');
9313 output_description_file_name = (char *) obstack_base (&irp);
9314 obstack_finish (&irp);
9317 /* The following function checks existence at least one arc marked by
9318 each insn. */
9319 static void
9320 check_automata_insn_issues (void)
9322 automaton_t automaton;
9323 ainsn_t ainsn, reserv_ainsn;
9325 for (automaton = description->first_automaton;
9326 automaton != NULL;
9327 automaton = automaton->next_automaton)
9329 for (ainsn = automaton->ainsn_list;
9330 ainsn != NULL;
9331 ainsn = ainsn->next_ainsn)
9332 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
9333 && ainsn != automaton->collapse_ainsn)
9335 for (reserv_ainsn = ainsn;
9336 reserv_ainsn != NULL;
9337 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9338 if (automaton->corresponding_automaton_decl != NULL)
9340 if (!w_flag)
9341 error ("Automaton `%s': Insn `%s' will never be issued",
9342 automaton->corresponding_automaton_decl->name,
9343 reserv_ainsn->insn_reserv_decl->name);
9344 else
9345 warning ("Automaton `%s': Insn `%s' will never be issued",
9346 automaton->corresponding_automaton_decl->name,
9347 reserv_ainsn->insn_reserv_decl->name);
9349 else
9351 if (!w_flag)
9352 error ("Insn `%s' will never be issued",
9353 reserv_ainsn->insn_reserv_decl->name);
9354 else
9355 warning ("Insn `%s' will never be issued",
9356 reserv_ainsn->insn_reserv_decl->name);
9362 /* The following vla is used for storing pointers to all achieved
9363 states. */
9364 static vec<state_t> automaton_states;
9366 /* This function is called by function pass_states to add an achieved
9367 STATE. */
9368 static void
9369 add_automaton_state (state_t state)
9371 automaton_states.safe_push (state);
9374 /* The following function forms list of important automata (whose
9375 states may be changed after the insn issue) for each insn. */
9376 static void
9377 form_important_insn_automata_lists (void)
9379 automaton_t automaton;
9380 decl_t decl;
9381 ainsn_t ainsn;
9382 arc_t arc;
9383 int i;
9384 size_t n;
9386 automaton_states.create (0);
9387 /* Mark important ainsns. */
9388 for (automaton = description->first_automaton;
9389 automaton != NULL;
9390 automaton = automaton->next_automaton)
9392 automaton_states.truncate (0);
9393 pass_states (automaton, add_automaton_state);
9394 for (n = 0; n < automaton_states.length (); n++)
9396 state_t s = automaton_states[n];
9397 for (arc = first_out_arc (s);
9398 arc != NULL;
9399 arc = next_out_arc (arc))
9400 if (arc->to_state != s)
9402 gcc_assert (arc->insn->first_insn_with_same_reservs);
9403 for (ainsn = arc->insn;
9404 ainsn != NULL;
9405 ainsn = ainsn->next_same_reservs_insn)
9406 ainsn->important_p = TRUE;
9410 automaton_states.release ();
9412 /* Create automata sets for the insns. */
9413 for (i = 0; i < description->decls_num; i++)
9415 decl = description->decls [i];
9416 if (decl->mode == dm_insn_reserv)
9418 automata_list_start ();
9419 for (automaton = description->first_automaton;
9420 automaton != NULL;
9421 automaton = automaton->next_automaton)
9422 for (ainsn = automaton->ainsn_list;
9423 ainsn != NULL;
9424 ainsn = ainsn->next_ainsn)
9425 if (ainsn->important_p
9426 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9428 automata_list_add (automaton);
9429 break;
9431 DECL_INSN_RESERV (decl)->important_automata_list
9432 = automata_list_finish ();
9438 /* The following is top level function to generate automat(a,on) for
9439 fast recognition of pipeline hazards. */
9440 static void
9441 expand_automata (void)
9443 int i;
9445 description = XCREATENODEVAR (struct description,
9446 sizeof (struct description)
9447 /* Two entries for special insns. */
9448 + sizeof (decl_t) * (decls.length () + 1));
9449 description->decls_num = decls.length ();
9450 description->normal_decls_num = description->decls_num;
9451 description->query_units_num = 0;
9452 for (i = 0; i < description->decls_num; i++)
9454 description->decls [i] = decls[i];
9455 if (description->decls [i]->mode == dm_unit
9456 && DECL_UNIT (description->decls [i])->query_p)
9457 DECL_UNIT (description->decls [i])->query_num
9458 = description->query_units_num++;
9460 all_time = create_ticker ();
9461 check_time = create_ticker ();
9462 if (progress_flag)
9463 fprintf (stderr, "Check description...");
9464 check_all_description ();
9465 if (progress_flag)
9466 fprintf (stderr, "done\n");
9467 ticker_off (&check_time);
9468 generation_time = create_ticker ();
9469 if (!have_error)
9471 transform_insn_regexps ();
9472 check_unit_distributions_to_automata ();
9474 if (!have_error)
9476 generate ();
9477 check_automata_insn_issues ();
9479 if (!have_error)
9481 form_important_insn_automata_lists ();
9483 ticker_off (&generation_time);
9486 /* The following is top level function to output PHR and to finish
9487 work with pipeline description translator. */
9488 static void
9489 write_automata (void)
9491 output_time = create_ticker ();
9492 if (progress_flag)
9493 fprintf (stderr, "Forming and outputting automata tables...");
9494 output_tables ();
9495 if (progress_flag)
9497 fprintf (stderr, "done\n");
9498 fprintf (stderr, "Output functions to work with automata...");
9500 output_chip_definitions ();
9501 output_max_insn_queue_index_def ();
9502 output_internal_min_issue_delay_func ();
9503 output_internal_trans_func ();
9504 /* Cache of insn dfa codes: */
9505 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9506 fprintf (output_file, "\nstatic int %s;\n\n",
9507 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9508 output_dfa_insn_code_func ();
9509 output_trans_func ();
9510 output_min_issue_delay_func ();
9511 output_internal_dead_lock_func ();
9512 output_dead_lock_func ();
9513 output_size_func ();
9514 output_internal_reset_func ();
9515 output_reset_func ();
9516 output_min_insn_conflict_delay_func ();
9517 output_default_latencies ();
9518 output_internal_insn_latency_func ();
9519 output_insn_latency_func ();
9520 output_internal_maximal_insn_latency_func ();
9521 output_maximal_insn_latency_func ();
9522 output_print_reservation_func ();
9523 /* Output function get_cpu_unit_code. */
9524 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9525 output_get_cpu_unit_code_func ();
9526 output_cpu_unit_reservation_p ();
9527 output_insn_has_dfa_reservation_p ();
9528 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9529 CPU_UNITS_QUERY_MACRO_NAME);
9530 output_dfa_clean_insn_cache_func ();
9531 output_dfa_start_func ();
9532 output_dfa_finish_func ();
9533 if (progress_flag)
9534 fprintf (stderr, "done\n");
9535 if (v_flag)
9537 output_description_file = fopen (output_description_file_name, "w");
9538 if (output_description_file == NULL)
9540 perror (output_description_file_name);
9541 exit (FATAL_EXIT_CODE);
9543 if (progress_flag)
9544 fprintf (stderr, "Output automata description...");
9545 output_description ();
9546 output_automaton_descriptions ();
9547 if (progress_flag)
9548 fprintf (stderr, "done\n");
9549 output_statistics (output_description_file);
9551 if (stats_flag)
9552 output_statistics (stderr);
9553 ticker_off (&output_time);
9554 if (time_flag)
9555 output_time_statistics (stderr);
9556 finish_states ();
9557 finish_arcs ();
9558 finish_automata_lists ();
9559 if (time_flag)
9561 fprintf (stderr, "Summary:\n");
9562 fprintf (stderr, " check time ");
9563 print_active_time (stderr, check_time);
9564 fprintf (stderr, ", generation time ");
9565 print_active_time (stderr, generation_time);
9566 fprintf (stderr, ", all time ");
9567 print_active_time (stderr, all_time);
9568 fprintf (stderr, "\n");
9570 /* Finish all work. */
9571 if (output_description_file != NULL)
9573 fflush (output_description_file);
9574 if (ferror (stdout) != 0)
9575 fatal ("Error in writing DFA description file %s: %s",
9576 output_description_file_name, xstrerror (errno));
9577 fclose (output_description_file);
9579 finish_automaton_decl_table ();
9580 finish_insn_decl_table ();
9581 finish_decl_table ();
9582 obstack_free (&irp, NULL);
9583 if (have_error && output_description_file != NULL)
9584 remove (output_description_file_name);
9588 main (int argc, char **argv)
9590 rtx desc;
9592 progname = "genautomata";
9594 if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
9595 return (FATAL_EXIT_CODE);
9597 initiate_automaton_gen (argv);
9598 while (1)
9600 int lineno;
9601 int insn_code_number;
9603 desc = read_md_rtx (&lineno, &insn_code_number);
9604 if (desc == NULL)
9605 break;
9607 switch (GET_CODE (desc))
9609 case DEFINE_CPU_UNIT:
9610 gen_cpu_unit (desc);
9611 break;
9613 case DEFINE_QUERY_CPU_UNIT:
9614 gen_query_cpu_unit (desc);
9615 break;
9617 case DEFINE_BYPASS:
9618 gen_bypass (desc);
9619 break;
9621 case EXCLUSION_SET:
9622 gen_excl_set (desc);
9623 break;
9625 case PRESENCE_SET:
9626 gen_presence_set (desc);
9627 break;
9629 case FINAL_PRESENCE_SET:
9630 gen_final_presence_set (desc);
9631 break;
9633 case ABSENCE_SET:
9634 gen_absence_set (desc);
9635 break;
9637 case FINAL_ABSENCE_SET:
9638 gen_final_absence_set (desc);
9639 break;
9641 case DEFINE_AUTOMATON:
9642 gen_automaton (desc);
9643 break;
9645 case AUTOMATA_OPTION:
9646 gen_automata_option (desc);
9647 break;
9649 case DEFINE_RESERVATION:
9650 gen_reserv (desc);
9651 break;
9653 case DEFINE_INSN_RESERVATION:
9654 gen_insn_reserv (desc);
9655 break;
9657 default:
9658 break;
9662 if (have_error)
9663 return FATAL_EXIT_CODE;
9665 if (decls.length () > 0)
9667 expand_automata ();
9668 if (!have_error)
9670 puts ("/* Generated automatically by the program `genautomata'\n"
9671 " from the machine description file `md'. */\n\n"
9672 "#include \"config.h\"\n"
9673 "#include \"system.h\"\n"
9674 "#include \"coretypes.h\"\n"
9675 "#include \"tm.h\"\n"
9676 "#include \"input.h\"\n"
9677 "#include \"alias.h\"\n"
9678 "#include \"symtab.h\"\n"
9679 "#include \"tree.h\"\n"
9680 "#include \"varasm.h\"\n"
9681 "#include \"stor-layout.h\"\n"
9682 "#include \"calls.h\"\n"
9683 "#include \"rtl.h\"\n"
9684 "#include \"tm_p.h\"\n"
9685 "#include \"insn-config.h\"\n"
9686 "#include \"recog.h\"\n"
9687 "#include \"regs.h\"\n"
9688 "#include \"output.h\"\n"
9689 "#include \"insn-attr.h\"\n"
9690 "#include \"diagnostic-core.h\"\n"
9691 "#include \"flags.h\"\n"
9692 "#include \"function.h\"\n"
9693 "#include \"emit-rtl.h\"\n");
9694 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9696 write_automata ();
9699 else
9701 puts ("/* Generated automatically by the program `genautomata'\n"
9702 " from the machine description file `md'. */\n\n"
9703 "/* There is no automaton, but ISO C forbids empty\n"
9704 " translation units, so include a header file with some\n"
9705 " declarations, and its pre-requisite header file. */\n"
9706 "#include \"config.h\"\n"
9707 "#include \"system.h\"\n");
9710 fflush (stdout);
9711 return (ferror (stdout) != 0 || have_error
9712 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);