2011-08-19 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / genautomata.c
blobe5260fa3c3d9ff0f9daf9690318150e264b09401
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
5 Written by Vladimir Makarov <vmakarov@redhat.com>
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 3, or (at your option) any
12 later version.
14 GCC is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
23 /* References:
25 1. The finite state automaton based pipeline hazard recognizer and
26 instruction scheduler in GCC. V. Makarov. Proceedings of GCC
27 summit, 2003.
29 2. Detecting pipeline structural hazards quickly. T. Proebsting,
30 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
31 Principles of Programming Languages, pages 280--286, 1994.
33 This article is a good start point to understand usage of finite
34 state automata for pipeline hazard recognizers. But I'd
35 recommend the 1st and 3rd article for more deep understanding.
37 3. Efficient Instruction Scheduling Using Finite State Automata:
38 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
39 article about usage of finite state automata for pipeline hazard
40 recognizers.
42 The current implementation is described in the 1st article and it
43 is different from the 3rd article in the following:
45 1. New operator `|' (alternative) is permitted in functional unit
46 reservation which can be treated deterministically and
47 non-deterministically.
49 2. Possibility of usage of nondeterministic automata too.
51 3. Possibility to query functional unit reservations for given
52 automaton state.
54 4. Several constructions to describe impossible reservations
55 (`exclusion_set', `presence_set', `final_presence_set',
56 `absence_set', and `final_absence_set').
58 5. No reverse automata are generated. Trace instruction scheduling
59 requires this. It can be easily added in the future if we
60 really need this.
62 6. Union of automaton states are not generated yet. It is planned
63 to be implemented. Such feature is needed to make more accurate
64 interlock insn scheduling to get state describing functional
65 unit reservation in a joint CFG point. */
67 /* This file code processes constructions of machine description file
68 which describes automaton used for recognition of processor pipeline
69 hazards by insn scheduler and can be used for other tasks (such as
70 VLIW insn packing.
72 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
73 `gen_bypass', `gen_excl_set', `gen_presence_set',
74 `gen_final_presence_set', `gen_absence_set',
75 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
76 `gen_reserv', `gen_insn_reserv' are called from file
77 `genattrtab.c'. They transform RTL constructions describing
78 automata in .md file into internal representation convenient for
79 further processing.
81 The translator major function `expand_automata' processes the
82 description internal representation into finite state automaton.
83 It can be divided on:
85 o checking correctness of the automaton pipeline description
86 (major function is `check_all_description').
88 o generating automaton (automata) from the description (major
89 function is `make_automaton').
91 o optional transformation of nondeterministic finite state
92 automata into deterministic ones if the alternative operator
93 `|' is treated nondeterministically in the description (major
94 function is NDFA_to_DFA).
96 o optional minimization of the finite state automata by merging
97 equivalent automaton states (major function is `minimize_DFA').
99 o forming tables (some as comb vectors) and attributes
100 representing the automata (functions output_..._table).
102 Function `write_automata' outputs the created finite state
103 automaton as different tables and functions which works with the
104 automata to inquire automaton state and to change its state. These
105 function are used by gcc instruction scheduler and may be some
106 other gcc code. */
108 #include "bconfig.h"
109 #include "system.h"
110 #include "coretypes.h"
111 #include "tm.h"
112 #include "rtl.h"
113 #include "obstack.h"
114 #include "errors.h"
115 #include "gensupport.h"
117 #include <math.h>
118 #include "hashtab.h"
119 #include "vec.h"
120 #include "fnmatch.h"
122 #ifndef CHAR_BIT
123 #define CHAR_BIT 8
124 #endif
126 /* Positions in machine description file. Now they are not used. But
127 they could be used in the future for better diagnostic messages. */
128 typedef int pos_t;
130 /* The following is element of vector of current (and planned in the
131 future) functional unit reservations. */
132 typedef unsigned HOST_WIDE_INT set_el_t;
134 /* Reservations of function units are represented by value of the following
135 type. */
136 typedef set_el_t *reserv_sets_t;
137 typedef const set_el_t *const_reserv_sets_t;
139 /* The following structure describes a ticker. */
140 struct ticker
142 /* The following member value is time of the ticker creation with
143 taking into account time when the ticker is off. Active time of
144 the ticker is current time minus the value. */
145 int modified_creation_time;
146 /* The following member value is time (incremented by one) when the
147 ticker was off. Zero value means that now the ticker is on. */
148 int incremented_off_time;
151 /* The ticker is represented by the following type. */
152 typedef struct ticker ticker_t;
154 /* The following type describes elements of output vectors. */
155 typedef HOST_WIDE_INT vect_el_t;
157 /* Forward declaration of structures of internal representation of
158 pipeline description based on NDFA. */
160 struct unit_decl;
161 struct bypass_decl;
162 struct result_decl;
163 struct automaton_decl;
164 struct unit_pattern_rel_decl;
165 struct reserv_decl;
166 struct insn_reserv_decl;
167 struct decl;
168 struct unit_regexp;
169 struct result_regexp;
170 struct reserv_regexp;
171 struct nothing_regexp;
172 struct sequence_regexp;
173 struct repeat_regexp;
174 struct allof_regexp;
175 struct oneof_regexp;
176 struct regexp;
177 struct description;
178 struct unit_set_el;
179 struct pattern_set_el;
180 struct pattern_reserv;
181 struct state;
182 struct alt_state;
183 struct arc;
184 struct ainsn;
185 struct automaton;
186 struct state_ainsn_table;
188 /* The following typedefs are for brevity. */
189 typedef struct unit_decl *unit_decl_t;
190 typedef const struct unit_decl *const_unit_decl_t;
191 typedef struct decl *decl_t;
192 typedef const struct decl *const_decl_t;
193 typedef struct regexp *regexp_t;
194 typedef struct unit_set_el *unit_set_el_t;
195 typedef struct pattern_set_el *pattern_set_el_t;
196 typedef struct pattern_reserv *pattern_reserv_t;
197 typedef struct alt_state *alt_state_t;
198 typedef struct state *state_t;
199 typedef const struct state *const_state_t;
200 typedef struct arc *arc_t;
201 typedef struct ainsn *ainsn_t;
202 typedef struct automaton *automaton_t;
203 typedef struct automata_list_el *automata_list_el_t;
204 typedef const struct automata_list_el *const_automata_list_el_t;
205 typedef struct state_ainsn_table *state_ainsn_table_t;
207 /* Undefined position. */
208 static pos_t no_pos = 0;
210 /* All IR is stored in the following obstack. */
211 static struct obstack irp;
214 /* Declare vector types for various data structures: */
216 DEF_VEC_P(alt_state_t);
217 DEF_VEC_ALLOC_P(alt_state_t, heap);
218 DEF_VEC_P(ainsn_t);
219 DEF_VEC_ALLOC_P(ainsn_t, heap);
220 DEF_VEC_P(state_t);
221 DEF_VEC_ALLOC_P(state_t, heap);
222 DEF_VEC_P(decl_t);
223 DEF_VEC_ALLOC_P(decl_t, heap);
224 DEF_VEC_P(reserv_sets_t);
225 DEF_VEC_ALLOC_P(reserv_sets_t, heap);
227 DEF_VEC_I(vect_el_t);
228 DEF_VEC_ALLOC_I(vect_el_t, heap);
229 typedef VEC(vect_el_t, heap) *vla_hwint_t;
231 /* Forward declarations of functions used before their definitions, only. */
232 static regexp_t gen_regexp_sequence (const char *);
233 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
234 reserv_sets_t);
235 static reserv_sets_t get_excl_set (reserv_sets_t);
236 static int check_presence_pattern_sets (reserv_sets_t,
237 reserv_sets_t, int);
238 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
239 int);
240 static arc_t first_out_arc (const_state_t);
241 static arc_t next_out_arc (arc_t);
245 /* Options with the following names can be set up in automata_option
246 construction. Because the strings occur more one time we use the
247 macros. */
249 #define NO_MINIMIZATION_OPTION "-no-minimization"
250 #define TIME_OPTION "-time"
251 #define STATS_OPTION "-stats"
252 #define V_OPTION "-v"
253 #define W_OPTION "-w"
254 #define NDFA_OPTION "-ndfa"
255 #define PROGRESS_OPTION "-progress"
257 /* The following flags are set up by function `initiate_automaton_gen'. */
259 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
260 static int ndfa_flag;
262 /* Do not make minimization of DFA (`-no-minimization'). */
263 static int no_minimization_flag;
265 /* Value of this variable is number of automata being generated. The
266 actual number of automata may be less this value if there is not
267 sufficient number of units. This value is defined by argument of
268 option `-split' or by constructions automaton if the value is zero
269 (it is default value of the argument). */
270 static int split_argument;
272 /* Flag of output time statistics (`-time'). */
273 static int time_flag;
275 /* Flag of automata statistics (`-stats'). */
276 static int stats_flag;
278 /* Flag of creation of description file which contains description of
279 result automaton and statistics information (`-v'). */
280 static int v_flag;
282 /* Flag of output of a progress bar showing how many states were
283 generated so far for automaton being processed (`-progress'). */
284 static int progress_flag;
286 /* Flag of generating warning instead of error for non-critical errors
287 (`-w'). */
288 static int w_flag;
291 /* Output file for pipeline hazard recognizer (PHR) being generated.
292 The value is NULL if the file is not defined. */
293 static FILE *output_file;
295 /* Description file of PHR. The value is NULL if the file is not
296 created. */
297 static FILE *output_description_file;
299 /* PHR description file name. */
300 static char *output_description_file_name;
302 /* Value of the following variable is node representing description
303 being processed. This is start point of IR. */
304 static struct description *description;
308 /* This page contains description of IR structure (nodes). */
310 enum decl_mode
312 dm_unit,
313 dm_bypass,
314 dm_automaton,
315 dm_excl,
316 dm_presence,
317 dm_absence,
318 dm_reserv,
319 dm_insn_reserv
322 /* This describes define_cpu_unit and define_query_cpu_unit (see file
323 rtl.def). */
324 struct unit_decl
326 const char *name;
327 /* NULL if the automaton name is absent. */
328 const char *automaton_name;
329 /* If the following value is not zero, the cpu unit reservation is
330 described in define_query_cpu_unit. */
331 char query_p;
333 /* The following fields are defined by checker. */
335 /* The following field value is nonzero if the unit is used in an
336 regexp. */
337 char unit_is_used;
339 /* The following field value is order number (0, 1, ...) of given
340 unit. */
341 int unit_num;
342 /* The following field value is corresponding declaration of
343 automaton which was given in description. If the field value is
344 NULL then automaton in the unit declaration was absent. */
345 struct automaton_decl *automaton_decl;
346 /* The following field value is maximal cycle number (1, ...) on
347 which given unit occurs in insns. Zero value means that given
348 unit is not used in insns. */
349 int max_occ_cycle_num;
350 /* The following field value is minimal cycle number (0, ...) on
351 which given unit occurs in insns. -1 value means that given
352 unit is not used in insns. */
353 int min_occ_cycle_num;
354 /* The following list contains units which conflict with given
355 unit. */
356 unit_set_el_t excl_list;
357 /* The following list contains patterns which are required to
358 reservation of given unit. */
359 pattern_set_el_t presence_list;
360 pattern_set_el_t final_presence_list;
361 /* The following list contains patterns which should be not present
362 in reservation for given unit. */
363 pattern_set_el_t absence_list;
364 pattern_set_el_t final_absence_list;
365 /* The following is used only when `query_p' has nonzero value.
366 This is query number for the unit. */
367 int query_num;
368 /* The following is the last cycle on which the unit was checked for
369 correct distributions of units to automata in a regexp. */
370 int last_distribution_check_cycle;
372 /* The following fields are defined by automaton generator. */
374 /* The following field value is number of the automaton to which
375 given unit belongs. */
376 int corresponding_automaton_num;
377 /* If the following value is not zero, the cpu unit is present in a
378 `exclusion_set' or in right part of a `presence_set',
379 `final_presence_set', `absence_set', and
380 `final_absence_set'define_query_cpu_unit. */
381 char in_set_p;
384 /* This describes define_bypass (see file rtl.def). */
385 struct bypass_decl
387 int latency;
388 const char *out_pattern;
389 const char *in_pattern;
390 const char *bypass_guard_name;
392 /* The following fields are defined by checker. */
394 /* output and input insns of given bypass. */
395 struct insn_reserv_decl *out_insn_reserv;
396 struct insn_reserv_decl *in_insn_reserv;
397 /* The next bypass for given output insn. */
398 struct bypass_decl *next;
401 /* This describes define_automaton (see file rtl.def). */
402 struct automaton_decl
404 const char *name;
406 /* The following fields are defined by automaton generator. */
408 /* The following field value is nonzero if the automaton is used in
409 an regexp definition. */
410 char automaton_is_used;
412 /* The following fields are defined by checker. */
414 /* The following field value is the corresponding automaton. This
415 field is not NULL only if the automaton is present in unit
416 declarations and the automatic partition on automata is not
417 used. */
418 automaton_t corresponding_automaton;
421 /* This describes exclusion relations: exclusion_set (see file
422 rtl.def). */
423 struct excl_rel_decl
425 int all_names_num;
426 int first_list_length;
427 char *names [1];
430 /* This describes unit relations: [final_]presence_set or
431 [final_]absence_set (see file rtl.def). */
432 struct unit_pattern_rel_decl
434 int final_p;
435 int names_num;
436 int patterns_num;
437 char **names;
438 char ***patterns;
441 /* This describes define_reservation (see file rtl.def). */
442 struct reserv_decl
444 const char *name;
445 regexp_t regexp;
447 /* The following fields are defined by checker. */
449 /* The following field value is nonzero if the unit is used in an
450 regexp. */
451 char reserv_is_used;
452 /* The following field is used to check up cycle in expression
453 definition. */
454 int loop_pass_num;
457 /* This describes define_insn_reservation (see file rtl.def). */
458 struct insn_reserv_decl
460 rtx condexp;
461 int default_latency;
462 regexp_t regexp;
463 const char *name;
465 /* The following fields are defined by checker. */
467 /* The following field value is order number (0, 1, ...) of given
468 insn. */
469 int insn_num;
470 /* The following field value is list of bypasses in which given insn
471 is output insn. Bypasses with the same input insn stay one after
472 another in the list in the same order as their occurrences in the
473 description but the bypass without a guard stays always the last
474 in a row of bypasses with the same input insn. */
475 struct bypass_decl *bypass_list;
477 /* The following fields are defined by automaton generator. */
479 /* The following field is the insn regexp transformed that
480 the regexp has not optional regexp, repetition regexp, and an
481 reservation name (i.e. reservation identifiers are changed by the
482 corresponding regexp) and all alternations are the top level
483 of the regexp. The value can be NULL only if it is special
484 insn `cycle advancing'. */
485 regexp_t transformed_regexp;
486 /* The following field value is list of arcs marked given
487 insn. The field is used in transformation NDFA -> DFA. */
488 arc_t arcs_marked_by_insn;
489 /* The two following fields are used during minimization of a finite state
490 automaton. */
491 /* The field value is number of equivalence class of state into
492 which arc marked by given insn enters from a state (fixed during
493 an automaton minimization). */
494 int equiv_class_num;
495 /* The following member value is the list to automata which can be
496 changed by the insn issue. */
497 automata_list_el_t important_automata_list;
498 /* The following member is used to process insn once for output. */
499 int processed_p;
502 /* This contains a declaration mentioned above. */
503 struct decl
505 /* What node in the union? */
506 enum decl_mode mode;
507 pos_t pos;
508 union
510 struct unit_decl unit;
511 struct bypass_decl bypass;
512 struct automaton_decl automaton;
513 struct excl_rel_decl excl;
514 struct unit_pattern_rel_decl presence;
515 struct unit_pattern_rel_decl absence;
516 struct reserv_decl reserv;
517 struct insn_reserv_decl insn_reserv;
518 } decl;
521 /* The following structures represent parsed reservation strings. */
522 enum regexp_mode
524 rm_unit,
525 rm_reserv,
526 rm_nothing,
527 rm_sequence,
528 rm_repeat,
529 rm_allof,
530 rm_oneof
533 /* Cpu unit in reservation. */
534 struct unit_regexp
536 const char *name;
537 unit_decl_t unit_decl;
540 /* Define_reservation in a reservation. */
541 struct reserv_regexp
543 const char *name;
544 struct reserv_decl *reserv_decl;
547 /* Absence of reservation (represented by string `nothing'). */
548 struct nothing_regexp
550 /* This used to be empty but ISO C doesn't allow that. */
551 char unused;
554 /* Representation of reservations separated by ',' (see file
555 rtl.def). */
556 struct sequence_regexp
558 int regexps_num;
559 regexp_t regexps [1];
562 /* Representation of construction `repeat' (see file rtl.def). */
563 struct repeat_regexp
565 int repeat_num;
566 regexp_t regexp;
569 /* Representation of reservations separated by '+' (see file
570 rtl.def). */
571 struct allof_regexp
573 int regexps_num;
574 regexp_t regexps [1];
577 /* Representation of reservations separated by '|' (see file
578 rtl.def). */
579 struct oneof_regexp
581 int regexps_num;
582 regexp_t regexps [1];
585 /* Representation of a reservation string. */
586 struct regexp
588 /* What node in the union? */
589 enum regexp_mode mode;
590 pos_t pos;
591 union
593 struct unit_regexp unit;
594 struct reserv_regexp reserv;
595 struct nothing_regexp nothing;
596 struct sequence_regexp sequence;
597 struct repeat_regexp repeat;
598 struct allof_regexp allof;
599 struct oneof_regexp oneof;
600 } regexp;
603 /* Represents description of pipeline hazard description based on
604 NDFA. */
605 struct description
607 int decls_num;
609 /* The following fields are defined by checker. */
611 /* The following fields values are correspondingly number of all
612 units, query units, and insns in the description. */
613 int units_num;
614 int query_units_num;
615 int insns_num;
616 /* The following field value is max length (in cycles) of
617 reservations of insns. The field value is defined only for
618 correct programs. */
619 int max_insn_reserv_cycles;
621 /* The following fields are defined by automaton generator. */
623 /* The following field value is the first automaton. */
624 automaton_t first_automaton;
626 /* The following field is created by pipeline hazard parser and
627 contains all declarations. We allocate additional entry for
628 special insn "cycle advancing" which is added by the automaton
629 generator. */
630 decl_t decls [1];
634 /* The following nodes are created in automaton checker. */
636 /* The following nodes represent exclusion set for cpu units. Each
637 element is accessed through only one excl_list. */
638 struct unit_set_el
640 unit_decl_t unit_decl;
641 unit_set_el_t next_unit_set_el;
644 /* The following nodes represent presence or absence pattern for cpu
645 units. Each element is accessed through only one presence_list or
646 absence_list. */
647 struct pattern_set_el
649 /* The number of units in unit_decls. */
650 int units_num;
651 /* The units forming the pattern. */
652 struct unit_decl **unit_decls;
653 pattern_set_el_t next_pattern_set_el;
657 /* The following nodes are created in automaton generator. */
660 /* The following nodes represent presence or absence pattern for cpu
661 units. Each element is accessed through only one element of
662 unit_presence_set_table or unit_absence_set_table. */
663 struct pattern_reserv
665 reserv_sets_t reserv;
666 pattern_reserv_t next_pattern_reserv;
669 /* The following node type describes state automaton. The state may
670 be deterministic or non-deterministic. Non-deterministic state has
671 several component states which represent alternative cpu units
672 reservations. The state also is used for describing a
673 deterministic reservation of automaton insn. */
674 struct state
676 /* The following member value is nonzero if there is a transition by
677 cycle advancing. */
678 int new_cycle_p;
679 /* The following field is list of processor unit reservations on
680 each cycle. */
681 reserv_sets_t reservs;
682 /* The following field is unique number of given state between other
683 states. */
684 int unique_num;
685 /* The following field value is automaton to which given state
686 belongs. */
687 automaton_t automaton;
688 /* The following field value is the first arc output from given
689 state. */
690 arc_t first_out_arc;
691 unsigned int num_out_arcs;
692 /* The following field is used to form NDFA. */
693 char it_was_placed_in_stack_for_NDFA_forming;
694 /* The following field is used to form DFA. */
695 char it_was_placed_in_stack_for_DFA_forming;
696 /* The following field is used to transform NDFA to DFA and DFA
697 minimization. The field value is not NULL if the state is a
698 compound state. In this case the value of field `unit_sets_list'
699 is NULL. All states in the list are in the hash table. The list
700 is formed through field `next_sorted_alt_state'. We should
701 support only one level of nesting state. */
702 alt_state_t component_states;
703 /* The following field is used for passing graph of states. */
704 int pass_num;
705 /* The list of states belonging to one equivalence class is formed
706 with the aid of the following field. */
707 state_t next_equiv_class_state;
708 /* The two following fields are used during minimization of a finite
709 state automaton. */
710 int equiv_class_num_1, equiv_class_num_2;
711 /* The following field is used during minimization of a finite state
712 automaton. The field value is state corresponding to equivalence
713 class to which given state belongs. */
714 state_t equiv_class_state;
715 unsigned int *presence_signature;
716 /* The following field value is the order number of given state.
717 The states in final DFA is enumerated with the aid of the
718 following field. */
719 int order_state_num;
720 /* This member is used for passing states for searching minimal
721 delay time. */
722 int state_pass_num;
723 /* The following member is used to evaluate min issue delay of insn
724 for a state. */
725 int min_insn_issue_delay;
728 /* Automaton arc. */
729 struct arc
731 /* The following field refers for the state into which given arc
732 enters. */
733 state_t to_state;
734 /* The following field describes that the insn issue (with cycle
735 advancing for special insn `cycle advancing' and without cycle
736 advancing for others) makes transition from given state to
737 another given state. */
738 ainsn_t insn;
739 /* The following field value is the next arc output from the same
740 state. */
741 arc_t next_out_arc;
742 /* List of arcs marked given insn is formed with the following
743 field. The field is used in transformation NDFA -> DFA. */
744 arc_t next_arc_marked_by_insn;
747 /* The following node type describes a deterministic alternative in
748 non-deterministic state which characterizes cpu unit reservations
749 of automaton insn or which is part of NDFA. */
750 struct alt_state
752 /* The following field is a deterministic state which characterizes
753 unit reservations of the instruction. */
754 state_t state;
755 /* The following field refers to the next state which characterizes
756 unit reservations of the instruction. */
757 alt_state_t next_alt_state;
758 /* The following field refers to the next state in sorted list. */
759 alt_state_t next_sorted_alt_state;
762 /* The following node type describes insn of automaton. They are
763 labels of FA arcs. */
764 struct ainsn
766 /* The following field value is the corresponding insn declaration
767 of description. */
768 struct insn_reserv_decl *insn_reserv_decl;
769 /* The following field value is the next insn declaration for an
770 automaton. */
771 ainsn_t next_ainsn;
772 /* The following field is states which characterize automaton unit
773 reservations of the instruction. The value can be NULL only if it
774 is special insn `cycle advancing'. */
775 alt_state_t alt_states;
776 /* The following field is sorted list of states which characterize
777 automaton unit reservations of the instruction. The value can be
778 NULL only if it is special insn `cycle advancing'. */
779 alt_state_t sorted_alt_states;
780 /* The following field refers the next automaton insn with
781 the same reservations. */
782 ainsn_t next_same_reservs_insn;
783 /* The following field is flag of the first automaton insn with the
784 same reservations in the declaration list. Only arcs marked such
785 insn is present in the automaton. This significantly decreases
786 memory requirements especially when several automata are
787 formed. */
788 char first_insn_with_same_reservs;
789 /* The following member has nonzero value if there is arc from state of
790 the automaton marked by the ainsn. */
791 char arc_exists_p;
792 /* Cyclic list of insns of an equivalence class is formed with the
793 aid of the following field. */
794 ainsn_t next_equiv_class_insn;
795 /* The following field value is nonzero if the insn declaration is
796 the first insn declaration with given equivalence number. */
797 char first_ainsn_with_given_equivalence_num;
798 /* The following field is number of class of equivalence of insns.
799 It is necessary because many insns may be equivalent with the
800 point of view of pipeline hazards. */
801 int insn_equiv_class_num;
802 /* The following member value is TRUE if there is an arc in the
803 automaton marked by the insn into another state. In other
804 words, the insn can change the state of the automaton. */
805 int important_p;
808 /* The following describes an automaton for PHR. */
809 struct automaton
811 /* The following field value is the list of insn declarations for
812 given automaton. */
813 ainsn_t ainsn_list;
814 /* The following field value is the corresponding automaton
815 declaration. This field is not NULL only if the automatic
816 partition on automata is not used. */
817 struct automaton_decl *corresponding_automaton_decl;
818 /* The following field value is the next automaton. */
819 automaton_t next_automaton;
820 /* The following field is start state of FA. There are not unit
821 reservations in the state. */
822 state_t start_state;
823 /* The following field value is number of equivalence classes of
824 insns (see field `insn_equiv_class_num' in
825 `insn_reserv_decl'). */
826 int insn_equiv_classes_num;
827 /* The following field value is number of states of final DFA. */
828 int achieved_states_num;
829 /* The following field value is the order number (0, 1, ...) of
830 given automaton. */
831 int automaton_order_num;
832 /* The following fields contain statistics information about
833 building automaton. */
834 int NDFA_states_num, DFA_states_num;
835 /* The following field value is defined only if minimization of DFA
836 is used. */
837 int minimal_DFA_states_num;
838 int NDFA_arcs_num, DFA_arcs_num;
839 /* The following field value is defined only if minimization of DFA
840 is used. */
841 int minimal_DFA_arcs_num;
842 /* The following member refers for two table state x ainsn -> int.
843 ??? Above sentence is incomprehensible. */
844 state_ainsn_table_t trans_table;
845 /* The following member value is maximal value of min issue delay
846 for insns of the automaton. */
847 int max_min_delay;
848 /* Usually min issue delay is small and we can place several (2, 4,
849 8) elements in one vector element. So the compression factor can
850 be 1 (no compression), 2, 4, 8. */
851 int min_issue_delay_table_compression_factor;
852 /* Total number of locked states in this automaton. */
853 int locked_states;
856 /* The following is the element of the list of automata. */
857 struct automata_list_el
859 /* The automaton itself. */
860 automaton_t automaton;
861 /* The next automata set element. */
862 automata_list_el_t next_automata_list_el;
865 /* The following structure describes a table state X ainsn -> int(>= 0). */
866 struct state_ainsn_table
868 /* Automaton to which given table belongs. */
869 automaton_t automaton;
870 /* The following tree vectors for comb vector implementation of the
871 table. */
872 vla_hwint_t comb_vect;
873 vla_hwint_t check_vect;
874 vla_hwint_t base_vect;
875 /* This is simple implementation of the table. */
876 vla_hwint_t full_vect;
877 /* Minimal and maximal values of the previous vectors. */
878 int min_comb_vect_el_value, max_comb_vect_el_value;
879 int min_base_vect_el_value, max_base_vect_el_value;
882 /* Macros to access members of unions. Use only them for access to
883 union members of declarations and regexps. */
885 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
887 #define DECL_UNIT(d) __extension__ \
888 (({ __typeof (d) const _decl = (d); \
889 if (_decl->mode != dm_unit) \
890 decl_mode_check_failed (_decl->mode, "dm_unit", \
891 __FILE__, __LINE__, __FUNCTION__); \
892 &(_decl)->decl.unit; }))
894 #define DECL_BYPASS(d) __extension__ \
895 (({ __typeof (d) const _decl = (d); \
896 if (_decl->mode != dm_bypass) \
897 decl_mode_check_failed (_decl->mode, "dm_bypass", \
898 __FILE__, __LINE__, __FUNCTION__); \
899 &(_decl)->decl.bypass; }))
901 #define DECL_AUTOMATON(d) __extension__ \
902 (({ __typeof (d) const _decl = (d); \
903 if (_decl->mode != dm_automaton) \
904 decl_mode_check_failed (_decl->mode, "dm_automaton", \
905 __FILE__, __LINE__, __FUNCTION__); \
906 &(_decl)->decl.automaton; }))
908 #define DECL_EXCL(d) __extension__ \
909 (({ __typeof (d) const _decl = (d); \
910 if (_decl->mode != dm_excl) \
911 decl_mode_check_failed (_decl->mode, "dm_excl", \
912 __FILE__, __LINE__, __FUNCTION__); \
913 &(_decl)->decl.excl; }))
915 #define DECL_PRESENCE(d) __extension__ \
916 (({ __typeof (d) const _decl = (d); \
917 if (_decl->mode != dm_presence) \
918 decl_mode_check_failed (_decl->mode, "dm_presence", \
919 __FILE__, __LINE__, __FUNCTION__); \
920 &(_decl)->decl.presence; }))
922 #define DECL_ABSENCE(d) __extension__ \
923 (({ __typeof (d) const _decl = (d); \
924 if (_decl->mode != dm_absence) \
925 decl_mode_check_failed (_decl->mode, "dm_absence", \
926 __FILE__, __LINE__, __FUNCTION__); \
927 &(_decl)->decl.absence; }))
929 #define DECL_RESERV(d) __extension__ \
930 (({ __typeof (d) const _decl = (d); \
931 if (_decl->mode != dm_reserv) \
932 decl_mode_check_failed (_decl->mode, "dm_reserv", \
933 __FILE__, __LINE__, __FUNCTION__); \
934 &(_decl)->decl.reserv; }))
936 #define DECL_INSN_RESERV(d) __extension__ \
937 (({ __typeof (d) const _decl = (d); \
938 if (_decl->mode != dm_insn_reserv) \
939 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
940 __FILE__, __LINE__, __FUNCTION__); \
941 &(_decl)->decl.insn_reserv; }))
943 static const char *decl_name (enum decl_mode);
944 static void decl_mode_check_failed (enum decl_mode, const char *,
945 const char *, int, const char *)
946 ATTRIBUTE_NORETURN;
948 /* Return string representation of declaration mode MODE. */
949 static const char *
950 decl_name (enum decl_mode mode)
952 static char str [100];
954 if (mode == dm_unit)
955 return "dm_unit";
956 else if (mode == dm_bypass)
957 return "dm_bypass";
958 else if (mode == dm_automaton)
959 return "dm_automaton";
960 else if (mode == dm_excl)
961 return "dm_excl";
962 else if (mode == dm_presence)
963 return "dm_presence";
964 else if (mode == dm_absence)
965 return "dm_absence";
966 else if (mode == dm_reserv)
967 return "dm_reserv";
968 else if (mode == dm_insn_reserv)
969 return "dm_insn_reserv";
970 else
971 sprintf (str, "unknown (%d)", (int) mode);
972 return str;
975 /* The function prints message about unexpected declaration and finish
976 the program. */
977 static void
978 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
979 const char *file, int line, const char *func)
981 fprintf
982 (stderr,
983 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
984 file, line, func, expected_mode_str, decl_name (mode));
985 exit (1);
989 #define REGEXP_UNIT(r) __extension__ \
990 (({ struct regexp *const _regexp = (r); \
991 if (_regexp->mode != rm_unit) \
992 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
993 __FILE__, __LINE__, __FUNCTION__); \
994 &(_regexp)->regexp.unit; }))
996 #define REGEXP_RESERV(r) __extension__ \
997 (({ struct regexp *const _regexp = (r); \
998 if (_regexp->mode != rm_reserv) \
999 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1000 __FILE__, __LINE__, __FUNCTION__); \
1001 &(_regexp)->regexp.reserv; }))
1003 #define REGEXP_SEQUENCE(r) __extension__ \
1004 (({ struct regexp *const _regexp = (r); \
1005 if (_regexp->mode != rm_sequence) \
1006 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1007 __FILE__, __LINE__, __FUNCTION__); \
1008 &(_regexp)->regexp.sequence; }))
1010 #define REGEXP_REPEAT(r) __extension__ \
1011 (({ struct regexp *const _regexp = (r); \
1012 if (_regexp->mode != rm_repeat) \
1013 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1014 __FILE__, __LINE__, __FUNCTION__); \
1015 &(_regexp)->regexp.repeat; }))
1017 #define REGEXP_ALLOF(r) __extension__ \
1018 (({ struct regexp *const _regexp = (r); \
1019 if (_regexp->mode != rm_allof) \
1020 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1021 __FILE__, __LINE__, __FUNCTION__); \
1022 &(_regexp)->regexp.allof; }))
1024 #define REGEXP_ONEOF(r) __extension__ \
1025 (({ struct regexp *const _regexp = (r); \
1026 if (_regexp->mode != rm_oneof) \
1027 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1028 __FILE__, __LINE__, __FUNCTION__); \
1029 &(_regexp)->regexp.oneof; }))
1031 static const char *regexp_name (enum regexp_mode);
1032 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1033 const char *, int,
1034 const char *) ATTRIBUTE_NORETURN;
1037 /* Return string representation of regexp mode MODE. */
1038 static const char *
1039 regexp_name (enum regexp_mode mode)
1041 switch (mode)
1043 case rm_unit:
1044 return "rm_unit";
1045 case rm_reserv:
1046 return "rm_reserv";
1047 case rm_nothing:
1048 return "rm_nothing";
1049 case rm_sequence:
1050 return "rm_sequence";
1051 case rm_repeat:
1052 return "rm_repeat";
1053 case rm_allof:
1054 return "rm_allof";
1055 case rm_oneof:
1056 return "rm_oneof";
1057 default:
1058 gcc_unreachable ();
1062 /* The function prints message about unexpected regexp and finish the
1063 program. */
1064 static void
1065 regexp_mode_check_failed (enum regexp_mode mode,
1066 const char *expected_mode_str,
1067 const char *file, int line, const char *func)
1069 fprintf
1070 (stderr,
1071 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1072 file, line, func, expected_mode_str, regexp_name (mode));
1073 exit (1);
1076 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1078 #define DECL_UNIT(d) (&(d)->decl.unit)
1079 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1080 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1081 #define DECL_EXCL(d) (&(d)->decl.excl)
1082 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1083 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1084 #define DECL_RESERV(d) (&(d)->decl.reserv)
1085 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1087 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1088 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1089 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1090 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1091 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1092 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1094 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1096 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1097 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1098 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1100 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1101 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1102 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1104 /* Create IR structure (node). */
1105 static void *
1106 create_node (size_t size)
1108 void *result;
1110 obstack_blank (&irp, size);
1111 result = obstack_base (&irp);
1112 obstack_finish (&irp);
1113 /* Default values of members are NULL and zero. */
1114 memset (result, 0, size);
1115 return result;
1118 /* Copy IR structure (node). */
1119 static void *
1120 copy_node (const void *from, size_t size)
1122 void *const result = create_node (size);
1123 memcpy (result, from, size);
1124 return result;
1127 /* The function checks that NAME does not contain quotes (`"'). */
1128 static const char *
1129 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1131 const char *str;
1133 for (str = name; *str != '\0'; str++)
1134 if (*str == '\"')
1135 error ("Name `%s' contains quotes", name);
1136 return name;
1139 /* Pointers to all declarations during IR generation are stored in the
1140 following. */
1141 static VEC(decl_t, heap) *decls;
1143 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1144 string containing the next separated element, taking parentheses
1145 into account if PAR_FLAG has nonzero value. Advance the pointer to
1146 after the string scanned, or the end-of-string. Return NULL if at
1147 end of string. */
1148 static char *
1149 next_sep_el (const char **pstr, int sep, int par_flag)
1151 char *out_str;
1152 const char *p;
1153 int pars_num;
1154 int n_spaces;
1156 /* Remove leading whitespaces. */
1157 while (ISSPACE ((int) **pstr))
1158 (*pstr)++;
1160 if (**pstr == '\0')
1161 return NULL;
1163 n_spaces = 0;
1164 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1166 if (par_flag && *p == '(')
1167 pars_num++;
1168 else if (par_flag && *p == ')')
1169 pars_num--;
1170 else if (pars_num == 0 && *p == sep)
1171 break;
1172 if (pars_num == 0 && ISSPACE ((int) *p))
1173 n_spaces++;
1174 else
1176 for (; n_spaces != 0; n_spaces--)
1177 obstack_1grow (&irp, p [-n_spaces]);
1178 obstack_1grow (&irp, *p);
1181 obstack_1grow (&irp, '\0');
1182 out_str = obstack_base (&irp);
1183 obstack_finish (&irp);
1185 *pstr = p;
1186 if (**pstr == sep)
1187 (*pstr)++;
1189 return out_str;
1192 /* Given a string and a separator, return the number of separated
1193 elements in it, taking parentheses into account if PAR_FLAG has
1194 nonzero value. Return 0 for the null string, -1 if parentheses is
1195 not balanced. */
1196 static int
1197 n_sep_els (const char *s, int sep, int par_flag)
1199 int n;
1200 int pars_num;
1202 if (*s == '\0')
1203 return 0;
1205 for (pars_num = 0, n = 1; *s; s++)
1206 if (par_flag && *s == '(')
1207 pars_num++;
1208 else if (par_flag && *s == ')')
1209 pars_num--;
1210 else if (pars_num == 0 && *s == sep)
1211 n++;
1213 return (pars_num != 0 ? -1 : n);
1216 /* Given a string and a separator, return vector of strings which are
1217 elements in the string and number of elements through els_num.
1218 Take parentheses into account if PAREN_P has nonzero value. The
1219 function also inserts the end marker NULL at the end of vector.
1220 Return 0 for the null string, -1 if parentheses are not balanced. */
1221 static char **
1222 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1224 int i;
1225 char **vect;
1226 const char **pstr;
1227 char *trail;
1229 *els_num = n_sep_els (str, sep, paren_p);
1230 if (*els_num <= 0)
1231 return NULL;
1232 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1233 vect = (char **) obstack_base (&irp);
1234 obstack_finish (&irp);
1235 pstr = &str;
1236 for (i = 0; i < *els_num; i++)
1237 vect [i] = next_sep_el (pstr, sep, paren_p);
1238 trail = next_sep_el (pstr, sep, paren_p);
1239 gcc_assert (!trail);
1240 vect [i] = NULL;
1241 return vect;
1244 /* Process a DEFINE_CPU_UNIT.
1246 This gives information about a unit contained in CPU. We fill a
1247 struct unit_decl with information used later by `expand_automata'. */
1248 static void
1249 gen_cpu_unit (rtx def)
1251 decl_t decl;
1252 char **str_cpu_units;
1253 int vect_length;
1254 int i;
1256 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1257 if (str_cpu_units == NULL)
1258 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1259 for (i = 0; i < vect_length; i++)
1261 decl = XCREATENODE (struct decl);
1262 decl->mode = dm_unit;
1263 decl->pos = 0;
1264 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1265 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1266 DECL_UNIT (decl)->query_p = 0;
1267 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1268 DECL_UNIT (decl)->in_set_p = 0;
1269 VEC_safe_push (decl_t, heap, decls, decl);
1273 /* Process a DEFINE_QUERY_CPU_UNIT.
1275 This gives information about a unit contained in CPU. We fill a
1276 struct unit_decl with information used later by `expand_automata'. */
1277 static void
1278 gen_query_cpu_unit (rtx def)
1280 decl_t decl;
1281 char **str_cpu_units;
1282 int vect_length;
1283 int i;
1285 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1286 FALSE);
1287 if (str_cpu_units == NULL)
1288 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1289 for (i = 0; i < vect_length; i++)
1291 decl = XCREATENODE (struct decl);
1292 decl->mode = dm_unit;
1293 decl->pos = 0;
1294 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1295 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1296 DECL_UNIT (decl)->query_p = 1;
1297 VEC_safe_push (decl_t, heap, decls, decl);
1301 /* Process a DEFINE_BYPASS.
1303 This gives information about a unit contained in the CPU. We fill
1304 in a struct bypass_decl with information used later by
1305 `expand_automata'. */
1306 static void
1307 gen_bypass (rtx def)
1309 decl_t decl;
1310 char **out_patterns;
1311 int out_length;
1312 char **in_patterns;
1313 int in_length;
1314 int i, j;
1316 out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1317 if (out_patterns == NULL)
1318 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1319 in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1320 if (in_patterns == NULL)
1321 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1322 for (i = 0; i < out_length; i++)
1323 for (j = 0; j < in_length; j++)
1325 decl = XCREATENODE (struct decl);
1326 decl->mode = dm_bypass;
1327 decl->pos = 0;
1328 DECL_BYPASS (decl)->latency = XINT (def, 0);
1329 DECL_BYPASS (decl)->out_pattern = out_patterns[i];
1330 DECL_BYPASS (decl)->in_pattern = in_patterns[j];
1331 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1332 VEC_safe_push (decl_t, heap, decls, decl);
1336 /* Process an EXCLUSION_SET.
1338 This gives information about a cpu unit conflicts. We fill a
1339 struct excl_rel_decl (excl) with information used later by
1340 `expand_automata'. */
1341 static void
1342 gen_excl_set (rtx def)
1344 decl_t decl;
1345 char **first_str_cpu_units;
1346 char **second_str_cpu_units;
1347 int first_vect_length;
1348 int length;
1349 int i;
1351 first_str_cpu_units
1352 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1353 if (first_str_cpu_units == NULL)
1354 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1355 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1356 FALSE);
1357 if (second_str_cpu_units == NULL)
1358 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1359 length += first_vect_length;
1360 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1361 decl->mode = dm_excl;
1362 decl->pos = 0;
1363 DECL_EXCL (decl)->all_names_num = length;
1364 DECL_EXCL (decl)->first_list_length = first_vect_length;
1365 for (i = 0; i < length; i++)
1366 if (i < first_vect_length)
1367 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1368 else
1369 DECL_EXCL (decl)->names [i]
1370 = second_str_cpu_units [i - first_vect_length];
1371 VEC_safe_push (decl_t, heap, decls, decl);
1374 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1375 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1377 This gives information about a cpu unit reservation requirements.
1378 We fill a struct unit_pattern_rel_decl with information used later
1379 by `expand_automata'. */
1380 static void
1381 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1383 decl_t decl;
1384 char **str_cpu_units;
1385 char **str_pattern_lists;
1386 char ***str_patterns;
1387 int cpu_units_length;
1388 int length;
1389 int patterns_length;
1390 int i;
1392 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1393 FALSE);
1394 if (str_cpu_units == NULL)
1395 fatal ((presence_p
1396 ? (final_p
1397 ? "invalid first string `%s' in final_presence_set"
1398 : "invalid first string `%s' in presence_set")
1399 : (final_p
1400 ? "invalid first string `%s' in final_absence_set"
1401 : "invalid first string `%s' in absence_set")),
1402 XSTR (def, 0));
1403 str_pattern_lists = get_str_vect (XSTR (def, 1),
1404 &patterns_length, ',', FALSE);
1405 if (str_pattern_lists == NULL)
1406 fatal ((presence_p
1407 ? (final_p
1408 ? "invalid second string `%s' in final_presence_set"
1409 : "invalid second string `%s' in presence_set")
1410 : (final_p
1411 ? "invalid second string `%s' in final_absence_set"
1412 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1413 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1414 for (i = 0; i < patterns_length; i++)
1416 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1417 &length, ' ', FALSE);
1418 gcc_assert (str_patterns [i]);
1420 decl = XCREATENODE (struct decl);
1421 decl->pos = 0;
1422 if (presence_p)
1424 decl->mode = dm_presence;
1425 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1426 DECL_PRESENCE (decl)->names = str_cpu_units;
1427 DECL_PRESENCE (decl)->patterns = str_patterns;
1428 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1429 DECL_PRESENCE (decl)->final_p = final_p;
1431 else
1433 decl->mode = dm_absence;
1434 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1435 DECL_ABSENCE (decl)->names = str_cpu_units;
1436 DECL_ABSENCE (decl)->patterns = str_patterns;
1437 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1438 DECL_ABSENCE (decl)->final_p = final_p;
1440 VEC_safe_push (decl_t, heap, decls, decl);
1443 /* Process a PRESENCE_SET.
1445 This gives information about a cpu unit reservation requirements.
1446 We fill a struct unit_pattern_rel_decl (presence) with information
1447 used later by `expand_automata'. */
1448 static void
1449 gen_presence_set (rtx def)
1451 gen_presence_absence_set (def, TRUE, FALSE);
1454 /* Process a FINAL_PRESENCE_SET.
1456 This gives information about a cpu unit reservation requirements.
1457 We fill a struct unit_pattern_rel_decl (presence) with information
1458 used later by `expand_automata'. */
1459 static void
1460 gen_final_presence_set (rtx def)
1462 gen_presence_absence_set (def, TRUE, TRUE);
1465 /* Process an ABSENCE_SET.
1467 This gives information about a cpu unit reservation requirements.
1468 We fill a struct unit_pattern_rel_decl (absence) with information
1469 used later by `expand_automata'. */
1470 static void
1471 gen_absence_set (rtx def)
1473 gen_presence_absence_set (def, FALSE, FALSE);
1476 /* Process a FINAL_ABSENCE_SET.
1478 This gives information about a cpu unit reservation requirements.
1479 We fill a struct unit_pattern_rel_decl (absence) with information
1480 used later by `expand_automata'. */
1481 static void
1482 gen_final_absence_set (rtx def)
1484 gen_presence_absence_set (def, FALSE, TRUE);
1487 /* Process a DEFINE_AUTOMATON.
1489 This gives information about a finite state automaton used for
1490 recognizing pipeline hazards. We fill a struct automaton_decl
1491 with information used later by `expand_automata'. */
1492 static void
1493 gen_automaton (rtx def)
1495 decl_t decl;
1496 char **str_automata;
1497 int vect_length;
1498 int i;
1500 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1501 if (str_automata == NULL)
1502 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1503 for (i = 0; i < vect_length; i++)
1505 decl = XCREATENODE (struct decl);
1506 decl->mode = dm_automaton;
1507 decl->pos = 0;
1508 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1509 VEC_safe_push (decl_t, heap, decls, decl);
1513 /* Process an AUTOMATA_OPTION.
1515 This gives information how to generate finite state automaton used
1516 for recognizing pipeline hazards. */
1517 static void
1518 gen_automata_option (rtx def)
1520 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1521 no_minimization_flag = 1;
1522 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1523 time_flag = 1;
1524 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1525 stats_flag = 1;
1526 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1527 v_flag = 1;
1528 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1529 w_flag = 1;
1530 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1531 ndfa_flag = 1;
1532 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1533 progress_flag = 1;
1534 else
1535 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1538 /* Name in reservation to denote absence reservation. */
1539 #define NOTHING_NAME "nothing"
1541 /* The following string contains original reservation string being
1542 parsed. */
1543 static const char *reserv_str;
1545 /* Parse an element in STR. */
1546 static regexp_t
1547 gen_regexp_el (const char *str)
1549 regexp_t regexp;
1550 char *dstr;
1551 int len;
1553 if (*str == '(')
1555 len = strlen (str);
1556 if (str [len - 1] != ')')
1557 fatal ("garbage after ) in reservation `%s'", reserv_str);
1558 dstr = XALLOCAVAR (char, len - 1);
1559 memcpy (dstr, str + 1, len - 2);
1560 dstr [len-2] = '\0';
1561 regexp = gen_regexp_sequence (dstr);
1563 else if (strcmp (str, NOTHING_NAME) == 0)
1565 regexp = XCREATENODE (struct regexp);
1566 regexp->mode = rm_nothing;
1568 else
1570 regexp = XCREATENODE (struct regexp);
1571 regexp->mode = rm_unit;
1572 REGEXP_UNIT (regexp)->name = str;
1574 return regexp;
1577 /* Parse construction `repeat' in STR. */
1578 static regexp_t
1579 gen_regexp_repeat (const char *str)
1581 regexp_t regexp;
1582 regexp_t repeat;
1583 char **repeat_vect;
1584 int els_num;
1585 int i;
1587 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1588 if (repeat_vect == NULL)
1589 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1590 if (els_num > 1)
1592 regexp = gen_regexp_el (repeat_vect [0]);
1593 for (i = 1; i < els_num; i++)
1595 repeat = XCREATENODE (struct regexp);
1596 repeat->mode = rm_repeat;
1597 REGEXP_REPEAT (repeat)->regexp = regexp;
1598 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1599 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1600 fatal ("repetition `%s' <= 1 in reservation `%s'",
1601 str, reserv_str);
1602 regexp = repeat;
1604 return regexp;
1606 else
1607 return gen_regexp_el (repeat_vect[0]);
1610 /* Parse reservation STR which possibly contains separator '+'. */
1611 static regexp_t
1612 gen_regexp_allof (const char *str)
1614 regexp_t allof;
1615 char **allof_vect;
1616 int els_num;
1617 int i;
1619 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1620 if (allof_vect == NULL)
1621 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1622 if (els_num > 1)
1624 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1625 + sizeof (regexp_t) * (els_num - 1));
1626 allof->mode = rm_allof;
1627 REGEXP_ALLOF (allof)->regexps_num = els_num;
1628 for (i = 0; i < els_num; i++)
1629 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1630 return allof;
1632 else
1633 return gen_regexp_repeat (allof_vect[0]);
1636 /* Parse reservation STR which possibly contains separator '|'. */
1637 static regexp_t
1638 gen_regexp_oneof (const char *str)
1640 regexp_t oneof;
1641 char **oneof_vect;
1642 int els_num;
1643 int i;
1645 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1646 if (oneof_vect == NULL)
1647 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1648 if (els_num > 1)
1650 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1651 + sizeof (regexp_t) * (els_num - 1));
1652 oneof->mode = rm_oneof;
1653 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1654 for (i = 0; i < els_num; i++)
1655 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1656 return oneof;
1658 else
1659 return gen_regexp_allof (oneof_vect[0]);
1662 /* Parse reservation STR which possibly contains separator ','. */
1663 static regexp_t
1664 gen_regexp_sequence (const char *str)
1666 regexp_t sequence;
1667 char **sequence_vect;
1668 int els_num;
1669 int i;
1671 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1672 if (els_num > 1)
1674 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1675 + sizeof (regexp_t) * (els_num - 1));
1676 sequence->mode = rm_sequence;
1677 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1678 for (i = 0; i < els_num; i++)
1679 REGEXP_SEQUENCE (sequence)->regexps [i]
1680 = gen_regexp_oneof (sequence_vect [i]);
1681 return sequence;
1683 else
1684 return gen_regexp_oneof (sequence_vect[0]);
1687 /* Parse construction reservation STR. */
1688 static regexp_t
1689 gen_regexp (const char *str)
1691 reserv_str = str;
1692 return gen_regexp_sequence (str);
1695 /* Process a DEFINE_RESERVATION.
1697 This gives information about a reservation of cpu units. We fill
1698 in a struct reserv_decl with information used later by
1699 `expand_automata'. */
1700 static void
1701 gen_reserv (rtx def)
1703 decl_t decl;
1705 decl = XCREATENODE (struct decl);
1706 decl->mode = dm_reserv;
1707 decl->pos = 0;
1708 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1709 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1710 VEC_safe_push (decl_t, heap, decls, decl);
1713 /* Process a DEFINE_INSN_RESERVATION.
1715 This gives information about the reservation of cpu units by an
1716 insn. We fill a struct insn_reserv_decl with information used
1717 later by `expand_automata'. */
1718 static void
1719 gen_insn_reserv (rtx def)
1721 decl_t decl;
1723 decl = XCREATENODE (struct decl);
1724 decl->mode = dm_insn_reserv;
1725 decl->pos = 0;
1726 DECL_INSN_RESERV (decl)->name
1727 = check_name (XSTR (def, 0), decl->pos);
1728 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1729 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1730 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1731 VEC_safe_push (decl_t, heap, decls, decl);
1736 /* The function evaluates hash value (0..UINT_MAX) of string. */
1737 static unsigned
1738 string_hash (const char *string)
1740 unsigned result, i;
1742 for (result = i = 0;*string++ != '\0'; i++)
1743 result += ((unsigned char) *string << (i % CHAR_BIT));
1744 return result;
1749 /* This page contains abstract data `table of automaton declarations'.
1750 Elements of the table is nodes representing automaton declarations.
1751 Key of the table elements is name of given automaton. Remember
1752 that automaton names have own space. */
1754 /* The function evaluates hash value of an automaton declaration. The
1755 function is used by abstract data `hashtab'. The function returns
1756 hash value (0..UINT_MAX) of given automaton declaration. */
1757 static hashval_t
1758 automaton_decl_hash (const void *automaton_decl)
1760 const_decl_t const decl = (const_decl_t) automaton_decl;
1762 gcc_assert (decl->mode != dm_automaton
1763 || DECL_AUTOMATON (decl)->name);
1764 return string_hash (DECL_AUTOMATON (decl)->name);
1767 /* The function tests automaton declarations on equality of their
1768 keys. The function is used by abstract data `hashtab'. The
1769 function returns 1 if the declarations have the same key, 0
1770 otherwise. */
1771 static int
1772 automaton_decl_eq_p (const void* automaton_decl_1,
1773 const void* automaton_decl_2)
1775 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1776 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1778 gcc_assert (decl1->mode == dm_automaton
1779 && DECL_AUTOMATON (decl1)->name
1780 && decl2->mode == dm_automaton
1781 && DECL_AUTOMATON (decl2)->name);
1782 return strcmp (DECL_AUTOMATON (decl1)->name,
1783 DECL_AUTOMATON (decl2)->name) == 0;
1786 /* The automaton declaration table itself is represented by the
1787 following variable. */
1788 static htab_t automaton_decl_table;
1790 /* The function inserts automaton declaration into the table. The
1791 function does nothing if an automaton declaration with the same key
1792 exists already in the table. The function returns automaton
1793 declaration node in the table with the same key as given automaton
1794 declaration node. */
1795 static decl_t
1796 insert_automaton_decl (decl_t automaton_decl)
1798 void **entry_ptr;
1800 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1801 if (*entry_ptr == NULL)
1802 *entry_ptr = (void *) automaton_decl;
1803 return (decl_t) *entry_ptr;
1806 /* The following variable value is node representing automaton
1807 declaration. The node used for searching automaton declaration
1808 with given name. */
1809 static struct decl work_automaton_decl;
1811 /* The function searches for automaton declaration in the table with
1812 the same key as node representing name of the automaton
1813 declaration. The function returns node found in the table, NULL if
1814 such node does not exist in the table. */
1815 static decl_t
1816 find_automaton_decl (const char *name)
1818 void *entry;
1820 work_automaton_decl.mode = dm_automaton;
1821 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1822 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1823 return (decl_t) entry;
1826 /* The function creates empty automaton declaration table and node
1827 representing automaton declaration and used for searching automaton
1828 declaration with given name. The function must be called only once
1829 before any work with the automaton declaration table. */
1830 static void
1831 initiate_automaton_decl_table (void)
1833 work_automaton_decl.mode = dm_automaton;
1834 automaton_decl_table = htab_create (10, automaton_decl_hash,
1835 automaton_decl_eq_p, (htab_del) 0);
1838 /* The function deletes the automaton declaration table. Only call of
1839 function `initiate_automaton_decl_table' is possible immediately
1840 after this function call. */
1841 static void
1842 finish_automaton_decl_table (void)
1844 htab_delete (automaton_decl_table);
1849 /* This page contains abstract data `table of insn declarations'.
1850 Elements of the table is nodes representing insn declarations. Key
1851 of the table elements is name of given insn (in corresponding
1852 define_insn_reservation). Remember that insn names have own
1853 space. */
1855 /* The function evaluates hash value of an insn declaration. The
1856 function is used by abstract data `hashtab'. The function returns
1857 hash value (0..UINT_MAX) of given insn declaration. */
1858 static hashval_t
1859 insn_decl_hash (const void *insn_decl)
1861 const_decl_t const decl = (const_decl_t) insn_decl;
1863 gcc_assert (decl->mode == dm_insn_reserv
1864 && DECL_INSN_RESERV (decl)->name);
1865 return string_hash (DECL_INSN_RESERV (decl)->name);
1868 /* The function tests insn declarations on equality of their keys.
1869 The function is used by abstract data `hashtab'. The function
1870 returns 1 if declarations have the same key, 0 otherwise. */
1871 static int
1872 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1874 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1875 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1877 gcc_assert (decl1->mode == dm_insn_reserv
1878 && DECL_INSN_RESERV (decl1)->name
1879 && decl2->mode == dm_insn_reserv
1880 && DECL_INSN_RESERV (decl2)->name);
1881 return strcmp (DECL_INSN_RESERV (decl1)->name,
1882 DECL_INSN_RESERV (decl2)->name) == 0;
1885 /* The insn declaration table itself is represented by the following
1886 variable. The table does not contain insn reservation
1887 declarations. */
1888 static htab_t insn_decl_table;
1890 /* The function inserts insn declaration into the table. The function
1891 does nothing if an insn declaration with the same key exists
1892 already in the table. The function returns insn declaration node
1893 in the table with the same key as given insn declaration node. */
1894 static decl_t
1895 insert_insn_decl (decl_t insn_decl)
1897 void **entry_ptr;
1899 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1900 if (*entry_ptr == NULL)
1901 *entry_ptr = (void *) insn_decl;
1902 return (decl_t) *entry_ptr;
1905 /* The following variable value is node representing insn reservation
1906 declaration. The node used for searching insn reservation
1907 declaration with given name. */
1908 static struct decl work_insn_decl;
1910 /* The function searches for insn reservation declaration in the table
1911 with the same key as node representing name of the insn reservation
1912 declaration. The function returns node found in the table, NULL if
1913 such node does not exist in the table. */
1914 static decl_t
1915 find_insn_decl (const char *name)
1917 void *entry;
1919 work_insn_decl.mode = dm_insn_reserv;
1920 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1921 entry = htab_find (insn_decl_table, &work_insn_decl);
1922 return (decl_t) entry;
1925 /* The function creates empty insn declaration table and node
1926 representing insn declaration and used for searching insn
1927 declaration with given name. The function must be called only once
1928 before any work with the insn declaration table. */
1929 static void
1930 initiate_insn_decl_table (void)
1932 work_insn_decl.mode = dm_insn_reserv;
1933 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1934 (htab_del) 0);
1937 /* The function deletes the insn declaration table. Only call of
1938 function `initiate_insn_decl_table' is possible immediately after
1939 this function call. */
1940 static void
1941 finish_insn_decl_table (void)
1943 htab_delete (insn_decl_table);
1948 /* This page contains abstract data `table of declarations'. Elements
1949 of the table is nodes representing declarations (of units and
1950 reservations). Key of the table elements is names of given
1951 declarations. */
1953 /* The function evaluates hash value of a declaration. The function
1954 is used by abstract data `hashtab'. The function returns hash
1955 value (0..UINT_MAX) of given declaration. */
1956 static hashval_t
1957 decl_hash (const void *decl)
1959 const_decl_t const d = (const_decl_t) decl;
1961 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1962 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1963 return string_hash (d->mode == dm_unit
1964 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1967 /* The function tests declarations on equality of their keys. The
1968 function is used by abstract data 'hashtab'. The function
1969 returns 1 if the declarations have the same key, 0 otherwise. */
1970 static int
1971 decl_eq_p (const void *decl_1, const void *decl_2)
1973 const_decl_t const d1 = (const_decl_t) decl_1;
1974 const_decl_t const d2 = (const_decl_t) decl_2;
1976 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1977 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1978 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1979 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1980 return strcmp ((d1->mode == dm_unit
1981 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1982 (d2->mode == dm_unit
1983 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1986 /* The declaration table itself is represented by the following
1987 variable. */
1988 static htab_t decl_table;
1990 /* The function inserts declaration into the table. The function does
1991 nothing if a declaration with the same key exists already in the
1992 table. The function returns declaration node in the table with the
1993 same key as given declaration node. */
1995 static decl_t
1996 insert_decl (decl_t decl)
1998 void **entry_ptr;
2000 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2001 if (*entry_ptr == NULL)
2002 *entry_ptr = (void *) decl;
2003 return (decl_t) *entry_ptr;
2006 /* The following variable value is node representing declaration. The
2007 node used for searching declaration with given name. */
2008 static struct decl work_decl;
2010 /* The function searches for declaration in the table with the same
2011 key as node representing name of the declaration. The function
2012 returns node found in the table, NULL if such node does not exist
2013 in the table. */
2014 static decl_t
2015 find_decl (const char *name)
2017 void *entry;
2019 work_decl.mode = dm_unit;
2020 DECL_UNIT (&work_decl)->name = name;
2021 entry = htab_find (decl_table, &work_decl);
2022 return (decl_t) entry;
2025 /* The function creates empty declaration table and node representing
2026 declaration and used for searching declaration with given name.
2027 The function must be called only once before any work with the
2028 declaration table. */
2029 static void
2030 initiate_decl_table (void)
2032 work_decl.mode = dm_unit;
2033 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2036 /* The function deletes the declaration table. Only call of function
2037 `initiate_declaration_table' is possible immediately after this
2038 function call. */
2039 static void
2040 finish_decl_table (void)
2042 htab_delete (decl_table);
2047 /* This page contains checker of pipeline hazard description. */
2049 /* Checking NAMES in an exclusion clause vector and returning formed
2050 unit_set_el_list. */
2051 static unit_set_el_t
2052 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2054 unit_set_el_t el_list;
2055 unit_set_el_t last_el;
2056 unit_set_el_t new_el;
2057 decl_t decl_in_table;
2058 int i;
2060 el_list = NULL;
2061 last_el = NULL;
2062 for (i = 0; i < num; i++)
2064 decl_in_table = find_decl (names [i]);
2065 if (decl_in_table == NULL)
2066 error ("unit `%s' in exclusion is not declared", names [i]);
2067 else if (decl_in_table->mode != dm_unit)
2068 error ("`%s' in exclusion is not unit", names [i]);
2069 else
2071 new_el = XCREATENODE (struct unit_set_el);
2072 new_el->unit_decl = DECL_UNIT (decl_in_table);
2073 new_el->next_unit_set_el = NULL;
2074 if (last_el == NULL)
2075 el_list = last_el = new_el;
2076 else
2078 last_el->next_unit_set_el = new_el;
2079 last_el = last_el->next_unit_set_el;
2083 return el_list;
2086 /* The function adds each element from SOURCE_LIST to the exclusion
2087 list of the each element from DEST_LIST. Checking situation "unit
2088 excludes itself". */
2089 static void
2090 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2091 pos_t excl_pos ATTRIBUTE_UNUSED)
2093 unit_set_el_t dst;
2094 unit_set_el_t src;
2095 unit_set_el_t curr_el;
2096 unit_set_el_t prev_el;
2097 unit_set_el_t copy;
2099 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2100 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2102 if (dst->unit_decl == src->unit_decl)
2104 error ("unit `%s' excludes itself", src->unit_decl->name);
2105 continue;
2107 if (dst->unit_decl->automaton_name != NULL
2108 && src->unit_decl->automaton_name != NULL
2109 && strcmp (dst->unit_decl->automaton_name,
2110 src->unit_decl->automaton_name) != 0)
2112 error ("units `%s' and `%s' in exclusion set belong to different automata",
2113 src->unit_decl->name, dst->unit_decl->name);
2114 continue;
2116 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2117 curr_el != NULL;
2118 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2119 if (curr_el->unit_decl == src->unit_decl)
2120 break;
2121 if (curr_el == NULL)
2123 /* Element not found - insert. */
2124 copy = XCOPYNODE (struct unit_set_el, src);
2125 copy->next_unit_set_el = NULL;
2126 if (prev_el == NULL)
2127 dst->unit_decl->excl_list = copy;
2128 else
2129 prev_el->next_unit_set_el = copy;
2134 /* Checking NAMES in presence/absence clause and returning the
2135 formed unit_set_el_list. The function is called only after
2136 processing all exclusion sets. */
2137 static unit_set_el_t
2138 process_presence_absence_names (char **names, int num,
2139 pos_t req_pos ATTRIBUTE_UNUSED,
2140 int presence_p, int final_p)
2142 unit_set_el_t el_list;
2143 unit_set_el_t last_el;
2144 unit_set_el_t new_el;
2145 decl_t decl_in_table;
2146 int i;
2148 el_list = NULL;
2149 last_el = NULL;
2150 for (i = 0; i < num; i++)
2152 decl_in_table = find_decl (names [i]);
2153 if (decl_in_table == NULL)
2154 error ((presence_p
2155 ? (final_p
2156 ? "unit `%s' in final presence set is not declared"
2157 : "unit `%s' in presence set is not declared")
2158 : (final_p
2159 ? "unit `%s' in final absence set is not declared"
2160 : "unit `%s' in absence set is not declared")), names [i]);
2161 else if (decl_in_table->mode != dm_unit)
2162 error ((presence_p
2163 ? (final_p
2164 ? "`%s' in final presence set is not unit"
2165 : "`%s' in presence set is not unit")
2166 : (final_p
2167 ? "`%s' in final absence set is not unit"
2168 : "`%s' in absence set is not unit")), names [i]);
2169 else
2171 new_el = XCREATENODE (struct unit_set_el);
2172 new_el->unit_decl = DECL_UNIT (decl_in_table);
2173 new_el->next_unit_set_el = NULL;
2174 if (last_el == NULL)
2175 el_list = last_el = new_el;
2176 else
2178 last_el->next_unit_set_el = new_el;
2179 last_el = last_el->next_unit_set_el;
2183 return el_list;
2186 /* Checking NAMES in patterns of a presence/absence clause and
2187 returning the formed pattern_set_el_list. The function is called
2188 only after processing all exclusion sets. */
2189 static pattern_set_el_t
2190 process_presence_absence_patterns (char ***patterns, int num,
2191 pos_t req_pos ATTRIBUTE_UNUSED,
2192 int presence_p, int final_p)
2194 pattern_set_el_t el_list;
2195 pattern_set_el_t last_el;
2196 pattern_set_el_t new_el;
2197 decl_t decl_in_table;
2198 int i, j;
2200 el_list = NULL;
2201 last_el = NULL;
2202 for (i = 0; i < num; i++)
2204 for (j = 0; patterns [i] [j] != NULL; j++)
2206 new_el = XCREATENODEVAR (struct pattern_set_el,
2207 sizeof (struct pattern_set_el)
2208 + sizeof (struct unit_decl *) * j);
2209 new_el->unit_decls
2210 = (struct unit_decl **) ((char *) new_el
2211 + sizeof (struct pattern_set_el));
2212 new_el->next_pattern_set_el = NULL;
2213 if (last_el == NULL)
2214 el_list = last_el = new_el;
2215 else
2217 last_el->next_pattern_set_el = new_el;
2218 last_el = last_el->next_pattern_set_el;
2220 new_el->units_num = 0;
2221 for (j = 0; patterns [i] [j] != NULL; j++)
2223 decl_in_table = find_decl (patterns [i] [j]);
2224 if (decl_in_table == NULL)
2225 error ((presence_p
2226 ? (final_p
2227 ? "unit `%s' in final presence set is not declared"
2228 : "unit `%s' in presence set is not declared")
2229 : (final_p
2230 ? "unit `%s' in final absence set is not declared"
2231 : "unit `%s' in absence set is not declared")),
2232 patterns [i] [j]);
2233 else if (decl_in_table->mode != dm_unit)
2234 error ((presence_p
2235 ? (final_p
2236 ? "`%s' in final presence set is not unit"
2237 : "`%s' in presence set is not unit")
2238 : (final_p
2239 ? "`%s' in final absence set is not unit"
2240 : "`%s' in absence set is not unit")),
2241 patterns [i] [j]);
2242 else
2244 new_el->unit_decls [new_el->units_num]
2245 = DECL_UNIT (decl_in_table);
2246 new_el->units_num++;
2250 return el_list;
2253 /* The function adds each element from PATTERN_LIST to presence (if
2254 PRESENCE_P) or absence list of the each element from DEST_LIST.
2255 Checking situations "unit requires own absence", and "unit excludes
2256 and requires presence of ...", "unit requires absence and presence
2257 of ...", "units in (final) presence set belong to different
2258 automata", and "units in (final) absence set belong to different
2259 automata". Remember that we process absence sets only after all
2260 presence sets. */
2261 static void
2262 add_presence_absence (unit_set_el_t dest_list,
2263 pattern_set_el_t pattern_list,
2264 pos_t req_pos ATTRIBUTE_UNUSED,
2265 int presence_p, int final_p)
2267 unit_set_el_t dst;
2268 pattern_set_el_t pat;
2269 struct unit_decl *unit;
2270 unit_set_el_t curr_excl_el;
2271 pattern_set_el_t curr_pat_el;
2272 pattern_set_el_t prev_el;
2273 pattern_set_el_t copy;
2274 int i;
2275 int no_error_flag;
2277 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2278 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2280 for (i = 0; i < pat->units_num; i++)
2282 unit = pat->unit_decls [i];
2283 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2285 error ("unit `%s' requires own absence", unit->name);
2286 continue;
2288 if (dst->unit_decl->automaton_name != NULL
2289 && unit->automaton_name != NULL
2290 && strcmp (dst->unit_decl->automaton_name,
2291 unit->automaton_name) != 0)
2293 error ((presence_p
2294 ? (final_p
2295 ? "units `%s' and `%s' in final presence set belong to different automata"
2296 : "units `%s' and `%s' in presence set belong to different automata")
2297 : (final_p
2298 ? "units `%s' and `%s' in final absence set belong to different automata"
2299 : "units `%s' and `%s' in absence set belong to different automata")),
2300 unit->name, dst->unit_decl->name);
2301 continue;
2303 no_error_flag = 1;
2304 if (presence_p)
2305 for (curr_excl_el = dst->unit_decl->excl_list;
2306 curr_excl_el != NULL;
2307 curr_excl_el = curr_excl_el->next_unit_set_el)
2309 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2311 if (!w_flag)
2313 error ("unit `%s' excludes and requires presence of `%s'",
2314 dst->unit_decl->name, unit->name);
2315 no_error_flag = 0;
2317 else
2318 warning ("unit `%s' excludes and requires presence of `%s'",
2319 dst->unit_decl->name, unit->name);
2322 else if (pat->units_num == 1)
2323 for (curr_pat_el = dst->unit_decl->presence_list;
2324 curr_pat_el != NULL;
2325 curr_pat_el = curr_pat_el->next_pattern_set_el)
2326 if (curr_pat_el->units_num == 1
2327 && unit == curr_pat_el->unit_decls [0])
2329 if (!w_flag)
2331 error ("unit `%s' requires absence and presence of `%s'",
2332 dst->unit_decl->name, unit->name);
2333 no_error_flag = 0;
2335 else
2336 warning ("unit `%s' requires absence and presence of `%s'",
2337 dst->unit_decl->name, unit->name);
2339 if (no_error_flag)
2341 for (prev_el = (presence_p
2342 ? (final_p
2343 ? dst->unit_decl->final_presence_list
2344 : dst->unit_decl->final_presence_list)
2345 : (final_p
2346 ? dst->unit_decl->final_absence_list
2347 : dst->unit_decl->absence_list));
2348 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2349 prev_el = prev_el->next_pattern_set_el)
2351 copy = XCOPYNODE (struct pattern_set_el, pat);
2352 copy->next_pattern_set_el = NULL;
2353 if (prev_el == NULL)
2355 if (presence_p)
2357 if (final_p)
2358 dst->unit_decl->final_presence_list = copy;
2359 else
2360 dst->unit_decl->presence_list = copy;
2362 else if (final_p)
2363 dst->unit_decl->final_absence_list = copy;
2364 else
2365 dst->unit_decl->absence_list = copy;
2367 else
2368 prev_el->next_pattern_set_el = copy;
2375 /* The function inserts BYPASS in the list of bypasses of the
2376 corresponding output insn. The order of bypasses in the list is
2377 decribed in a comment for member `bypass_list' (see above). If
2378 there is already the same bypass in the list the function reports
2379 this and does nothing. */
2380 static void
2381 insert_bypass (struct bypass_decl *bypass)
2383 struct bypass_decl *curr, *last;
2384 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2385 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2387 for (curr = out_insn_reserv->bypass_list, last = NULL;
2388 curr != NULL;
2389 last = curr, curr = curr->next)
2390 if (curr->in_insn_reserv == in_insn_reserv)
2392 if ((bypass->bypass_guard_name != NULL
2393 && curr->bypass_guard_name != NULL
2394 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2395 || bypass->bypass_guard_name == curr->bypass_guard_name)
2397 if (bypass->bypass_guard_name == NULL)
2399 if (!w_flag)
2400 error ("the same bypass `%s - %s' is already defined",
2401 bypass->out_pattern, bypass->in_pattern);
2402 else
2403 warning ("the same bypass `%s - %s' is already defined",
2404 bypass->out_pattern, bypass->in_pattern);
2406 else if (!w_flag)
2407 error ("the same bypass `%s - %s' (guard %s) is already defined",
2408 bypass->out_pattern, bypass->in_pattern,
2409 bypass->bypass_guard_name);
2410 else
2411 warning
2412 ("the same bypass `%s - %s' (guard %s) is already defined",
2413 bypass->out_pattern, bypass->in_pattern,
2414 bypass->bypass_guard_name);
2415 return;
2417 if (curr->bypass_guard_name == NULL)
2418 break;
2419 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2421 last = curr;
2422 break;
2426 if (last == NULL)
2428 bypass->next = out_insn_reserv->bypass_list;
2429 out_insn_reserv->bypass_list = bypass;
2431 else
2433 bypass->next = last->next;
2434 last->next = bypass;
2438 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2439 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2441 static void
2442 for_each_matching_insn (decl_t bypass, const char *pattern,
2443 void (*fn) (decl_t, decl_t, void *), void *data)
2445 decl_t insn_reserv;
2446 bool matched_p;
2447 int i;
2449 matched_p = false;
2450 if (strpbrk (pattern, "*?["))
2451 for (i = 0; i < description->decls_num; i++)
2453 insn_reserv = description->decls[i];
2454 if (insn_reserv->mode == dm_insn_reserv
2455 && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
2457 fn (bypass, insn_reserv, data);
2458 matched_p = true;
2461 else
2463 insn_reserv = find_insn_decl (pattern);
2464 if (insn_reserv)
2466 fn (bypass, insn_reserv, data);
2467 matched_p = true;
2470 if (!matched_p)
2471 error ("there is no insn reservation that matches `%s'", pattern);
2474 /* A subroutine of process_bypass that is called for each pair
2475 of matching instructions. OUT_INSN_RESERV is the output
2476 instruction and DATA is the input instruction. */
2478 static void
2479 process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
2481 struct bypass_decl *bypass;
2482 decl_t in_insn_reserv;
2484 in_insn_reserv = (decl_t) data;
2485 if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
2486 DECL_BYPASS (model)->in_pattern) == 0
2487 && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
2488 DECL_BYPASS (model)->out_pattern) == 0)
2489 bypass = DECL_BYPASS (model);
2490 else
2492 bypass = XCNEW (struct bypass_decl);
2493 bypass->latency = DECL_BYPASS (model)->latency;
2494 bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
2495 bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
2496 bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
2498 bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
2499 bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
2500 insert_bypass (bypass);
2503 /* A subroutine of process_bypass that is called for each input
2504 instruction IN_INSN_RESERV. */
2506 static void
2507 process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
2508 void *data ATTRIBUTE_UNUSED)
2510 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
2511 process_bypass_2, in_insn_reserv);
2514 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2515 pair of insn reservations. */
2517 static void
2518 process_bypass (decl_t bypass)
2520 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
2521 process_bypass_1, NULL);
2524 /* The function processes pipeline description declarations, checks
2525 their correctness, and forms exclusion/presence/absence sets. */
2526 static void
2527 process_decls (void)
2529 decl_t decl;
2530 decl_t automaton_decl;
2531 decl_t decl_in_table;
2532 int automaton_presence;
2533 int i;
2535 /* Checking repeated automata declarations. */
2536 automaton_presence = 0;
2537 for (i = 0; i < description->decls_num; i++)
2539 decl = description->decls [i];
2540 if (decl->mode == dm_automaton)
2542 automaton_presence = 1;
2543 decl_in_table = insert_automaton_decl (decl);
2544 if (decl_in_table != decl)
2546 if (!w_flag)
2547 error ("repeated declaration of automaton `%s'",
2548 DECL_AUTOMATON (decl)->name);
2549 else
2550 warning ("repeated declaration of automaton `%s'",
2551 DECL_AUTOMATON (decl)->name);
2555 /* Checking undeclared automata, repeated declarations (except for
2556 automata) and correctness of their attributes (insn latency times
2557 etc.). */
2558 for (i = 0; i < description->decls_num; i++)
2560 decl = description->decls [i];
2561 if (decl->mode == dm_insn_reserv)
2563 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2564 error ("define_insn_reservation `%s' has negative latency time",
2565 DECL_INSN_RESERV (decl)->name);
2566 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2567 description->insns_num++;
2568 decl_in_table = insert_insn_decl (decl);
2569 if (decl_in_table != decl)
2570 error ("`%s' is already used as insn reservation name",
2571 DECL_INSN_RESERV (decl)->name);
2573 else if (decl->mode == dm_bypass)
2575 if (DECL_BYPASS (decl)->latency < 0)
2576 error ("define_bypass `%s - %s' has negative latency time",
2577 DECL_BYPASS (decl)->out_pattern,
2578 DECL_BYPASS (decl)->in_pattern);
2580 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2582 if (decl->mode == dm_unit)
2584 DECL_UNIT (decl)->automaton_decl = NULL;
2585 if (DECL_UNIT (decl)->automaton_name != NULL)
2587 automaton_decl
2588 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2589 if (automaton_decl == NULL)
2590 error ("automaton `%s' is not declared",
2591 DECL_UNIT (decl)->automaton_name);
2592 else
2594 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2595 DECL_UNIT (decl)->automaton_decl
2596 = DECL_AUTOMATON (automaton_decl);
2599 else if (automaton_presence)
2600 error ("define_unit `%s' without automaton when one defined",
2601 DECL_UNIT (decl)->name);
2602 DECL_UNIT (decl)->unit_num = description->units_num;
2603 description->units_num++;
2604 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2606 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2607 continue;
2609 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2611 else
2613 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2615 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2616 continue;
2618 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2620 if (decl_in_table == NULL)
2621 decl_in_table = insert_decl (decl);
2622 else
2624 if (decl->mode == dm_unit)
2625 error ("repeated declaration of unit `%s'",
2626 DECL_UNIT (decl)->name);
2627 else
2628 error ("repeated declaration of reservation `%s'",
2629 DECL_RESERV (decl)->name);
2633 /* Check bypasses and form list of bypasses for each (output)
2634 insn. */
2635 for (i = 0; i < description->decls_num; i++)
2637 decl = description->decls [i];
2638 if (decl->mode == dm_bypass)
2639 process_bypass (decl);
2642 /* Check exclusion set declarations and form exclusion sets. */
2643 for (i = 0; i < description->decls_num; i++)
2645 decl = description->decls [i];
2646 if (decl->mode == dm_excl)
2648 unit_set_el_t unit_set_el_list;
2649 unit_set_el_t unit_set_el_list_2;
2651 unit_set_el_list
2652 = process_excls (DECL_EXCL (decl)->names,
2653 DECL_EXCL (decl)->first_list_length, decl->pos);
2654 unit_set_el_list_2
2655 = process_excls (&DECL_EXCL (decl)->names
2656 [DECL_EXCL (decl)->first_list_length],
2657 DECL_EXCL (decl)->all_names_num
2658 - DECL_EXCL (decl)->first_list_length,
2659 decl->pos);
2660 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2661 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2665 /* Check presence set declarations and form presence sets. */
2666 for (i = 0; i < description->decls_num; i++)
2668 decl = description->decls [i];
2669 if (decl->mode == dm_presence)
2671 unit_set_el_t unit_set_el_list;
2672 pattern_set_el_t pattern_set_el_list;
2674 unit_set_el_list
2675 = process_presence_absence_names
2676 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2677 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2678 pattern_set_el_list
2679 = process_presence_absence_patterns
2680 (DECL_PRESENCE (decl)->patterns,
2681 DECL_PRESENCE (decl)->patterns_num,
2682 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2683 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2684 decl->pos, TRUE,
2685 DECL_PRESENCE (decl)->final_p);
2689 /* Check absence set declarations and form absence sets. */
2690 for (i = 0; i < description->decls_num; i++)
2692 decl = description->decls [i];
2693 if (decl->mode == dm_absence)
2695 unit_set_el_t unit_set_el_list;
2696 pattern_set_el_t pattern_set_el_list;
2698 unit_set_el_list
2699 = process_presence_absence_names
2700 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2701 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2702 pattern_set_el_list
2703 = process_presence_absence_patterns
2704 (DECL_ABSENCE (decl)->patterns,
2705 DECL_ABSENCE (decl)->patterns_num,
2706 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2707 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2708 decl->pos, FALSE,
2709 DECL_ABSENCE (decl)->final_p);
2714 /* The following function checks that declared automaton is used. If
2715 the automaton is not used, the function fixes error/warning. The
2716 following function must be called only after `process_decls'. */
2717 static void
2718 check_automaton_usage (void)
2720 decl_t decl;
2721 int i;
2723 for (i = 0; i < description->decls_num; i++)
2725 decl = description->decls [i];
2726 if (decl->mode == dm_automaton
2727 && !DECL_AUTOMATON (decl)->automaton_is_used)
2729 if (!w_flag)
2730 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2731 else
2732 warning ("automaton `%s' is not used",
2733 DECL_AUTOMATON (decl)->name);
2738 /* The following recursive function processes all regexp in order to
2739 fix usage of units or reservations and to fix errors of undeclared
2740 name. The function may change unit_regexp onto reserv_regexp.
2741 Remember that reserv_regexp does not exist before the function
2742 call. */
2743 static regexp_t
2744 process_regexp (regexp_t regexp)
2746 decl_t decl_in_table;
2747 regexp_t new_regexp;
2748 int i;
2750 switch (regexp->mode)
2752 case rm_unit:
2753 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2754 if (decl_in_table == NULL)
2755 error ("undeclared unit or reservation `%s'",
2756 REGEXP_UNIT (regexp)->name);
2757 else
2758 switch (decl_in_table->mode)
2760 case dm_unit:
2761 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2762 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2763 break;
2765 case dm_reserv:
2766 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2767 new_regexp = XCREATENODE (struct regexp);
2768 new_regexp->mode = rm_reserv;
2769 new_regexp->pos = regexp->pos;
2770 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2771 REGEXP_RESERV (new_regexp)->reserv_decl
2772 = DECL_RESERV (decl_in_table);
2773 regexp = new_regexp;
2774 break;
2776 default:
2777 gcc_unreachable ();
2779 break;
2780 case rm_sequence:
2781 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2782 REGEXP_SEQUENCE (regexp)->regexps [i]
2783 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2784 break;
2785 case rm_allof:
2786 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2787 REGEXP_ALLOF (regexp)->regexps [i]
2788 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2789 break;
2790 case rm_oneof:
2791 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2792 REGEXP_ONEOF (regexp)->regexps [i]
2793 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2794 break;
2795 case rm_repeat:
2796 REGEXP_REPEAT (regexp)->regexp
2797 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2798 break;
2799 case rm_nothing:
2800 break;
2801 default:
2802 gcc_unreachable ();
2804 return regexp;
2807 /* The following function processes regexp of define_reservation and
2808 define_insn_reservation with the aid of function
2809 `process_regexp'. */
2810 static void
2811 process_regexp_decls (void)
2813 decl_t decl;
2814 int i;
2816 for (i = 0; i < description->decls_num; i++)
2818 decl = description->decls [i];
2819 if (decl->mode == dm_reserv)
2820 DECL_RESERV (decl)->regexp
2821 = process_regexp (DECL_RESERV (decl)->regexp);
2822 else if (decl->mode == dm_insn_reserv)
2823 DECL_INSN_RESERV (decl)->regexp
2824 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2828 /* The following function checks that declared unit is used. If the
2829 unit is not used, the function fixes errors/warnings. The
2830 following function must be called only after `process_decls',
2831 `process_regexp_decls'. */
2832 static void
2833 check_usage (void)
2835 decl_t decl;
2836 int i;
2838 for (i = 0; i < description->decls_num; i++)
2840 decl = description->decls [i];
2841 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2843 if (!w_flag)
2844 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2845 else
2846 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2848 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2850 if (!w_flag)
2851 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2852 else
2853 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2858 /* The following variable value is number of reservation being
2859 processed on loop recognition. */
2860 static int curr_loop_pass_num;
2862 /* The following recursive function returns nonzero value if REGEXP
2863 contains given decl or reservations in given regexp refers for
2864 given decl. */
2865 static int
2866 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2868 int i;
2870 if (regexp == NULL)
2871 return 0;
2872 switch (regexp->mode)
2874 case rm_unit:
2875 return 0;
2877 case rm_reserv:
2878 if (start_decl->mode == dm_reserv
2879 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2880 return 1;
2881 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2882 == curr_loop_pass_num)
2883 /* declaration has been processed. */
2884 return 0;
2885 else
2887 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2888 = curr_loop_pass_num;
2889 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2890 start_decl);
2893 case rm_sequence:
2894 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2895 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2896 return 1;
2897 return 0;
2899 case rm_allof:
2900 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2901 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2902 return 1;
2903 return 0;
2905 case rm_oneof:
2906 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2907 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2908 return 1;
2909 return 0;
2911 case rm_repeat:
2912 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2914 case rm_nothing:
2915 return 0;
2917 default:
2918 gcc_unreachable ();
2922 /* The following function fixes errors "cycle in definition ...". The
2923 function uses function `loop_in_regexp' for that. */
2924 static void
2925 check_loops_in_regexps (void)
2927 decl_t decl;
2928 int i;
2930 for (i = 0; i < description->decls_num; i++)
2932 decl = description->decls [i];
2933 if (decl->mode == dm_reserv)
2934 DECL_RESERV (decl)->loop_pass_num = 0;
2936 for (i = 0; i < description->decls_num; i++)
2938 decl = description->decls [i];
2939 curr_loop_pass_num = i;
2941 if (decl->mode == dm_reserv)
2943 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2944 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2946 gcc_assert (DECL_RESERV (decl)->regexp);
2947 error ("cycle in definition of reservation `%s'",
2948 DECL_RESERV (decl)->name);
2954 /* The function recursively processes IR of reservation and defines
2955 max and min cycle for reservation of unit. */
2956 static void
2957 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2958 int min_start_cycle, int *max_finish_cycle,
2959 int *min_finish_cycle)
2961 int i;
2963 switch (regexp->mode)
2965 case rm_unit:
2966 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2967 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2968 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2969 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2970 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2971 *max_finish_cycle = max_start_cycle;
2972 *min_finish_cycle = min_start_cycle;
2973 break;
2975 case rm_reserv:
2976 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2977 max_start_cycle, min_start_cycle,
2978 max_finish_cycle, min_finish_cycle);
2979 break;
2981 case rm_repeat:
2982 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2984 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2985 max_start_cycle, min_start_cycle,
2986 max_finish_cycle, min_finish_cycle);
2987 max_start_cycle = *max_finish_cycle + 1;
2988 min_start_cycle = *min_finish_cycle + 1;
2990 break;
2992 case rm_sequence:
2993 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2995 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2996 max_start_cycle, min_start_cycle,
2997 max_finish_cycle, min_finish_cycle);
2998 max_start_cycle = *max_finish_cycle + 1;
2999 min_start_cycle = *min_finish_cycle + 1;
3001 break;
3003 case rm_allof:
3005 int max_cycle = 0;
3006 int min_cycle = 0;
3008 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3010 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3011 max_start_cycle, min_start_cycle,
3012 max_finish_cycle, min_finish_cycle);
3013 if (max_cycle < *max_finish_cycle)
3014 max_cycle = *max_finish_cycle;
3015 if (i == 0 || min_cycle > *min_finish_cycle)
3016 min_cycle = *min_finish_cycle;
3018 *max_finish_cycle = max_cycle;
3019 *min_finish_cycle = min_cycle;
3021 break;
3023 case rm_oneof:
3025 int max_cycle = 0;
3026 int min_cycle = 0;
3028 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3030 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3031 max_start_cycle, min_start_cycle,
3032 max_finish_cycle, min_finish_cycle);
3033 if (max_cycle < *max_finish_cycle)
3034 max_cycle = *max_finish_cycle;
3035 if (i == 0 || min_cycle > *min_finish_cycle)
3036 min_cycle = *min_finish_cycle;
3038 *max_finish_cycle = max_cycle;
3039 *min_finish_cycle = min_cycle;
3041 break;
3043 case rm_nothing:
3044 *max_finish_cycle = max_start_cycle;
3045 *min_finish_cycle = min_start_cycle;
3046 break;
3048 default:
3049 gcc_unreachable ();
3053 /* The following function is called only for correct program. The
3054 function defines max reservation of insns in cycles. */
3055 static void
3056 evaluate_max_reserv_cycles (void)
3058 int max_insn_cycles_num;
3059 int min_insn_cycles_num;
3060 decl_t decl;
3061 int i;
3063 description->max_insn_reserv_cycles = 0;
3064 for (i = 0; i < description->decls_num; i++)
3066 decl = description->decls [i];
3067 if (decl->mode == dm_insn_reserv)
3069 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3070 &max_insn_cycles_num, &min_insn_cycles_num);
3071 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3072 description->max_insn_reserv_cycles = max_insn_cycles_num;
3075 description->max_insn_reserv_cycles++;
3078 /* The following function calls functions for checking all
3079 description. */
3080 static void
3081 check_all_description (void)
3083 process_decls ();
3084 check_automaton_usage ();
3085 process_regexp_decls ();
3086 check_usage ();
3087 check_loops_in_regexps ();
3088 if (!have_error)
3089 evaluate_max_reserv_cycles ();
3094 /* The page contains abstract data `ticker'. This data is used to
3095 report time of different phases of building automata. It is
3096 possibly to write a description for which automata will be built
3097 during several minutes even on fast machine. */
3099 /* The following function creates ticker and makes it active. */
3100 static ticker_t
3101 create_ticker (void)
3103 ticker_t ticker;
3105 ticker.modified_creation_time = get_run_time ();
3106 ticker.incremented_off_time = 0;
3107 return ticker;
3110 /* The following function switches off given ticker. */
3111 static void
3112 ticker_off (ticker_t *ticker)
3114 if (ticker->incremented_off_time == 0)
3115 ticker->incremented_off_time = get_run_time () + 1;
3118 /* The following function switches on given ticker. */
3119 static void
3120 ticker_on (ticker_t *ticker)
3122 if (ticker->incremented_off_time != 0)
3124 ticker->modified_creation_time
3125 += get_run_time () - ticker->incremented_off_time + 1;
3126 ticker->incremented_off_time = 0;
3130 /* The following function returns current time in milliseconds since
3131 the moment when given ticker was created. */
3132 static int
3133 active_time (ticker_t ticker)
3135 if (ticker.incremented_off_time != 0)
3136 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3137 else
3138 return get_run_time () - ticker.modified_creation_time;
3141 /* The following function returns string representation of active time
3142 of given ticker. The result is string representation of seconds
3143 with accuracy of 1/100 second. Only result of the last call of the
3144 function exists. Therefore the following code is not correct
3146 printf ("parser time: %s\ngeneration time: %s\n",
3147 active_time_string (parser_ticker),
3148 active_time_string (generation_ticker));
3150 Correct code has to be the following
3152 printf ("parser time: %s\n", active_time_string (parser_ticker));
3153 printf ("generation time: %s\n",
3154 active_time_string (generation_ticker));
3157 static void
3158 print_active_time (FILE *f, ticker_t ticker)
3160 int msecs;
3162 msecs = active_time (ticker);
3163 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3168 /* The following variable value is number of automaton which are
3169 really being created. This value is defined on the base of
3170 argument of option `-split'. If the variable has zero value the
3171 number of automata is defined by the constructions `%automaton'.
3172 This case occurs when option `-split' is absent or has zero
3173 argument. If constructions `define_automaton' is absent only one
3174 automaton is created. */
3175 static int automata_num;
3177 /* The following variable values are times of
3178 o transformation of regular expressions
3179 o building NDFA (DFA if !ndfa_flag)
3180 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3181 o DFA minimization
3182 o building insn equivalence classes
3183 o all previous ones
3184 o code output */
3185 static ticker_t transform_time;
3186 static ticker_t NDFA_time;
3187 static ticker_t NDFA_to_DFA_time;
3188 static ticker_t minimize_time;
3189 static ticker_t equiv_time;
3190 static ticker_t automaton_generation_time;
3191 static ticker_t output_time;
3193 /* The following variable values are times of
3194 all checking
3195 all generation
3196 all pipeline hazard translator work */
3197 static ticker_t check_time;
3198 static ticker_t generation_time;
3199 static ticker_t all_time;
3203 /* Pseudo insn decl which denotes advancing cycle. */
3204 static decl_t advance_cycle_insn_decl;
3205 static void
3206 add_advance_cycle_insn_decl (void)
3208 advance_cycle_insn_decl = XCREATENODE (struct decl);
3209 advance_cycle_insn_decl->mode = dm_insn_reserv;
3210 advance_cycle_insn_decl->pos = no_pos;
3211 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3212 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3213 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3214 = description->insns_num;
3215 description->decls [description->decls_num] = advance_cycle_insn_decl;
3216 description->decls_num++;
3217 description->insns_num++;
3221 /* Abstract data `alternative states' which represents
3222 nondeterministic nature of the description (see comments for
3223 structures alt_state and state). */
3225 /* List of free states. */
3226 static alt_state_t first_free_alt_state;
3228 #ifndef NDEBUG
3229 /* The following variables is maximal number of allocated nodes
3230 alt_state. */
3231 static int allocated_alt_states_num = 0;
3232 #endif
3234 /* The following function returns free node alt_state. It may be new
3235 allocated node or node freed earlier. */
3236 static alt_state_t
3237 get_free_alt_state (void)
3239 alt_state_t result;
3241 if (first_free_alt_state != NULL)
3243 result = first_free_alt_state;
3244 first_free_alt_state = first_free_alt_state->next_alt_state;
3246 else
3248 #ifndef NDEBUG
3249 allocated_alt_states_num++;
3250 #endif
3251 result = XCREATENODE (struct alt_state);
3253 result->state = NULL;
3254 result->next_alt_state = NULL;
3255 result->next_sorted_alt_state = NULL;
3256 return result;
3259 /* The function frees node ALT_STATE. */
3260 static void
3261 free_alt_state (alt_state_t alt_state)
3263 if (alt_state == NULL)
3264 return;
3265 alt_state->next_alt_state = first_free_alt_state;
3266 first_free_alt_state = alt_state;
3269 /* The function frees list started with node ALT_STATE_LIST. */
3270 static void
3271 free_alt_states (alt_state_t alt_states_list)
3273 alt_state_t curr_alt_state;
3274 alt_state_t next_alt_state;
3276 for (curr_alt_state = alt_states_list;
3277 curr_alt_state != NULL;
3278 curr_alt_state = next_alt_state)
3280 next_alt_state = curr_alt_state->next_alt_state;
3281 free_alt_state (curr_alt_state);
3285 /* The function compares unique numbers of alt states. */
3286 static int
3287 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3289 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3290 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3291 return 0;
3292 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3293 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3294 return -1;
3295 else
3296 return 1;
3299 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3300 states from the list. The comparison key is alt state unique
3301 number. */
3303 static alt_state_t
3304 uniq_sort_alt_states (alt_state_t alt_states_list)
3306 alt_state_t curr_alt_state;
3307 VEC(alt_state_t, heap) *alt_states;
3308 size_t i;
3309 size_t prev_unique_state_ind;
3310 alt_state_t result;
3312 if (alt_states_list == 0)
3313 return 0;
3314 if (alt_states_list->next_alt_state == 0)
3315 return alt_states_list;
3317 alt_states = VEC_alloc (alt_state_t, heap, 150);
3318 for (curr_alt_state = alt_states_list;
3319 curr_alt_state != NULL;
3320 curr_alt_state = curr_alt_state->next_alt_state)
3321 VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state);
3323 VEC_qsort (alt_state_t, alt_states, alt_state_cmp);
3325 prev_unique_state_ind = 0;
3326 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3327 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3328 != VEC_index (alt_state_t, alt_states, i)->state)
3330 prev_unique_state_ind++;
3331 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3332 VEC_index (alt_state_t, alt_states, i));
3334 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3336 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3337 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3338 = VEC_index (alt_state_t, alt_states, i);
3339 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3341 result = VEC_index (alt_state_t, alt_states, 0);
3343 VEC_free (alt_state_t, heap, alt_states);
3344 return result;
3347 /* The function checks equality of alt state lists. Remember that the
3348 lists must be already sorted by the previous function. */
3349 static int
3350 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3352 while (alt_states_1 != NULL && alt_states_2 != NULL
3353 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3355 alt_states_1 = alt_states_1->next_sorted_alt_state;
3356 alt_states_2 = alt_states_2->next_sorted_alt_state;
3358 return alt_states_1 == alt_states_2;
3361 /* Initialization of the abstract data. */
3362 static void
3363 initiate_alt_states (void)
3365 first_free_alt_state = NULL;
3368 /* Finishing work with the abstract data. */
3369 static void
3370 finish_alt_states (void)
3376 /* The page contains macros for work with bits strings. We could use
3377 standard gcc bitmap or sbitmap but it would result in difficulties
3378 of building canadian cross. */
3380 /* Set bit number bitno in the bit string. The macro is not side
3381 effect proof. */
3382 #define SET_BIT(bitstring, bitno) \
3383 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3384 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3386 #define CLEAR_BIT(bitstring, bitno) \
3387 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3388 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3390 /* Test if bit number bitno in the bitstring is set. The macro is not
3391 side effect proof. */
3392 #define TEST_BIT(bitstring, bitno) \
3393 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3394 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3398 /* This page contains abstract data `state'. */
3400 /* Maximal length of reservations in cycles (>= 1). */
3401 static int max_cycles_num;
3403 /* Number of set elements (see type set_el_t) needed for
3404 representation of one cycle reservation. It is depended on units
3405 number. */
3406 static int els_in_cycle_reserv;
3408 /* Number of set elements (see type set_el_t) needed for
3409 representation of maximal length reservation. Deterministic
3410 reservation is stored as set (bit string) of length equal to the
3411 variable value * number of bits in set_el_t. */
3412 static int els_in_reservs;
3414 /* Array of pointers to unit declarations. */
3415 static unit_decl_t *units_array;
3417 /* Temporary reservation of maximal length. */
3418 static reserv_sets_t temp_reserv;
3420 /* The state table itself is represented by the following variable. */
3421 static htab_t state_table;
3423 /* Linked list of free 'state' structures to be recycled. The
3424 next_equiv_class_state pointer is borrowed for a free list. */
3425 static state_t first_free_state;
3427 static int curr_unique_state_num;
3429 #ifndef NDEBUG
3430 /* The following variables is maximal number of allocated nodes
3431 `state'. */
3432 static int allocated_states_num = 0;
3433 #endif
3435 /* Allocate new reservation set. */
3436 static reserv_sets_t
3437 alloc_empty_reserv_sets (void)
3439 reserv_sets_t result;
3441 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3442 result = (reserv_sets_t) obstack_base (&irp);
3443 obstack_finish (&irp);
3444 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3445 return result;
3448 /* Hash value of reservation set. */
3449 static unsigned
3450 reserv_sets_hash_value (reserv_sets_t reservs)
3452 set_el_t hash_value;
3453 unsigned result;
3454 int reservs_num, i;
3455 set_el_t *reserv_ptr;
3457 hash_value = 0;
3458 reservs_num = els_in_reservs;
3459 reserv_ptr = reservs;
3460 i = 0;
3461 while (reservs_num != 0)
3463 reservs_num--;
3464 hash_value += ((*reserv_ptr >> i)
3465 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3466 i++;
3467 if (i == sizeof (set_el_t) * CHAR_BIT)
3468 i = 0;
3469 reserv_ptr++;
3471 if (sizeof (set_el_t) <= sizeof (unsigned))
3472 return hash_value;
3473 result = 0;
3474 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3476 result += (unsigned) hash_value;
3477 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3479 return result;
3482 /* Comparison of given reservation sets. */
3483 static int
3484 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3486 int reservs_num;
3487 const set_el_t *reserv_ptr_1;
3488 const set_el_t *reserv_ptr_2;
3490 gcc_assert (reservs_1 && reservs_2);
3491 reservs_num = els_in_reservs;
3492 reserv_ptr_1 = reservs_1;
3493 reserv_ptr_2 = reservs_2;
3494 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3496 reservs_num--;
3497 reserv_ptr_1++;
3498 reserv_ptr_2++;
3500 if (reservs_num == 0)
3501 return 0;
3502 else if (*reserv_ptr_1 < *reserv_ptr_2)
3503 return -1;
3504 else
3505 return 1;
3508 /* The function checks equality of the reservation sets. */
3509 static int
3510 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3512 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3515 /* Set up in the reservation set that unit with UNIT_NUM is used on
3516 CYCLE_NUM. */
3517 static void
3518 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3520 gcc_assert (cycle_num < max_cycles_num);
3521 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3522 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3525 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3526 used on CYCLE_NUM. */
3527 static int
3528 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3530 gcc_assert (cycle_num < max_cycles_num);
3531 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3532 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3535 /* The function checks that the reservation sets are intersected,
3536 i.e. there is a unit reservation on a cycle in both reservation
3537 sets. */
3538 static int
3539 reserv_sets_are_intersected (reserv_sets_t operand_1,
3540 reserv_sets_t operand_2)
3542 set_el_t *el_ptr_1;
3543 set_el_t *el_ptr_2;
3544 set_el_t *cycle_ptr_1;
3545 set_el_t *cycle_ptr_2;
3547 gcc_assert (operand_1 && operand_2);
3548 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3549 el_ptr_1 < operand_1 + els_in_reservs;
3550 el_ptr_1++, el_ptr_2++)
3551 if (*el_ptr_1 & *el_ptr_2)
3552 return 1;
3553 reserv_sets_or (temp_reserv, operand_1, operand_2);
3554 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3555 cycle_ptr_1 < operand_1 + els_in_reservs;
3556 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3558 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3559 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3560 el_ptr_1++, el_ptr_2++)
3561 if (*el_ptr_1 & *el_ptr_2)
3562 return 1;
3563 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3564 return 1;
3565 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3566 - operand_2),
3567 cycle_ptr_2, TRUE))
3568 return 1;
3569 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3570 return 1;
3571 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3572 cycle_ptr_2, TRUE))
3573 return 1;
3575 return 0;
3578 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3579 cpu cycle. The remaining bits of OPERAND (representing the last
3580 cycle unit reservations) are not changed. */
3581 static void
3582 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3584 int i;
3586 gcc_assert (result && operand && result != operand);
3587 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3588 result [i - els_in_cycle_reserv] = operand [i];
3591 /* OR of the reservation sets. */
3592 static void
3593 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3594 reserv_sets_t operand_2)
3596 set_el_t *el_ptr_1;
3597 set_el_t *el_ptr_2;
3598 set_el_t *result_set_el_ptr;
3600 gcc_assert (result && operand_1 && operand_2);
3601 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3602 el_ptr_1 < operand_1 + els_in_reservs;
3603 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3604 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3607 /* AND of the reservation sets. */
3608 static void
3609 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3610 reserv_sets_t operand_2)
3612 set_el_t *el_ptr_1;
3613 set_el_t *el_ptr_2;
3614 set_el_t *result_set_el_ptr;
3616 gcc_assert (result && operand_1 && operand_2);
3617 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3618 el_ptr_1 < operand_1 + els_in_reservs;
3619 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3620 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3623 /* The function outputs string representation of units reservation on
3624 cycle START_CYCLE in the reservation set. The function uses repeat
3625 construction if REPETITION_NUM > 1. */
3626 static void
3627 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3628 int repetition_num)
3630 int unit_num;
3631 int reserved_units_num;
3633 reserved_units_num = 0;
3634 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3635 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3636 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3637 reserved_units_num++;
3638 gcc_assert (repetition_num > 0);
3639 if (repetition_num != 1 && reserved_units_num > 1)
3640 fprintf (f, "(");
3641 reserved_units_num = 0;
3642 for (unit_num = 0;
3643 unit_num < description->units_num;
3644 unit_num++)
3645 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3646 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3648 if (reserved_units_num != 0)
3649 fprintf (f, "+");
3650 reserved_units_num++;
3651 fprintf (f, "%s", units_array [unit_num]->name);
3653 if (reserved_units_num == 0)
3654 fprintf (f, NOTHING_NAME);
3655 gcc_assert (repetition_num > 0);
3656 if (repetition_num != 1 && reserved_units_num > 1)
3657 fprintf (f, ")");
3658 if (repetition_num != 1)
3659 fprintf (f, "*%d", repetition_num);
3662 /* The function outputs string representation of units reservation in
3663 the reservation set. */
3664 static void
3665 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3667 int start_cycle = 0;
3668 int cycle;
3669 int repetition_num;
3671 repetition_num = 0;
3672 for (cycle = 0; cycle < max_cycles_num; cycle++)
3673 if (repetition_num == 0)
3675 repetition_num++;
3676 start_cycle = cycle;
3678 else if (memcmp
3679 ((char *) reservs + start_cycle * els_in_cycle_reserv
3680 * sizeof (set_el_t),
3681 (char *) reservs + cycle * els_in_cycle_reserv
3682 * sizeof (set_el_t),
3683 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3684 repetition_num++;
3685 else
3687 if (start_cycle != 0)
3688 fprintf (f, ", ");
3689 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3690 repetition_num = 1;
3691 start_cycle = cycle;
3693 if (start_cycle < max_cycles_num)
3695 if (start_cycle != 0)
3696 fprintf (f, ", ");
3697 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3701 /* The following function returns free node state for AUTOMATON. It
3702 may be new allocated node or node freed earlier. The function also
3703 allocates reservation set if WITH_RESERVS has nonzero value. */
3704 static state_t
3705 get_free_state (int with_reservs, automaton_t automaton)
3707 state_t result;
3709 gcc_assert (max_cycles_num > 0 && automaton);
3710 if (first_free_state)
3712 result = first_free_state;
3713 first_free_state = result->next_equiv_class_state;
3715 result->next_equiv_class_state = NULL;
3716 result->automaton = automaton;
3717 result->first_out_arc = NULL;
3718 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3719 result->it_was_placed_in_stack_for_DFA_forming = 0;
3720 result->component_states = NULL;
3722 else
3724 #ifndef NDEBUG
3725 allocated_states_num++;
3726 #endif
3727 result = XCREATENODE (struct state);
3728 result->automaton = automaton;
3729 result->first_out_arc = NULL;
3730 result->unique_num = curr_unique_state_num;
3731 curr_unique_state_num++;
3733 if (with_reservs)
3735 if (result->reservs == NULL)
3736 result->reservs = alloc_empty_reserv_sets ();
3737 else
3738 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3740 return result;
3743 /* The function frees node STATE. */
3744 static void
3745 free_state (state_t state)
3747 free_alt_states (state->component_states);
3748 state->next_equiv_class_state = first_free_state;
3749 first_free_state = state;
3752 /* Hash value of STATE. If STATE represents deterministic state it is
3753 simply hash value of the corresponding reservation set. Otherwise
3754 it is formed from hash values of the component deterministic
3755 states. One more key is order number of state automaton. */
3756 static hashval_t
3757 state_hash (const void *state)
3759 unsigned int hash_value;
3760 alt_state_t alt_state;
3762 if (((const_state_t) state)->component_states == NULL)
3763 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3764 else
3766 hash_value = 0;
3767 for (alt_state = ((const_state_t) state)->component_states;
3768 alt_state != NULL;
3769 alt_state = alt_state->next_sorted_alt_state)
3770 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3771 | (hash_value << CHAR_BIT))
3772 + alt_state->state->unique_num);
3774 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3775 | (hash_value << CHAR_BIT))
3776 + ((const_state_t) state)->automaton->automaton_order_num);
3777 return hash_value;
3780 /* Return nonzero value if the states are the same. */
3781 static int
3782 state_eq_p (const void *state_1, const void *state_2)
3784 alt_state_t alt_state_1;
3785 alt_state_t alt_state_2;
3787 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3788 return 0;
3789 else if (((const_state_t) state_1)->component_states == NULL
3790 && ((const_state_t) state_2)->component_states == NULL)
3791 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3792 ((const_state_t) state_2)->reservs);
3793 else if (((const_state_t) state_1)->component_states != NULL
3794 && ((const_state_t) state_2)->component_states != NULL)
3796 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3797 alt_state_2 = ((const_state_t) state_2)->component_states;
3798 alt_state_1 != NULL && alt_state_2 != NULL;
3799 alt_state_1 = alt_state_1->next_sorted_alt_state,
3800 alt_state_2 = alt_state_2->next_sorted_alt_state)
3801 /* All state in the list must be already in the hash table.
3802 Also the lists must be sorted. */
3803 if (alt_state_1->state != alt_state_2->state)
3804 return 0;
3805 return alt_state_1 == alt_state_2;
3807 else
3808 return 0;
3811 /* Insert STATE into the state table. */
3812 static state_t
3813 insert_state (state_t state)
3815 void **entry_ptr;
3817 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3818 if (*entry_ptr == NULL)
3819 *entry_ptr = (void *) state;
3820 return (state_t) *entry_ptr;
3823 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3824 deterministic STATE. */
3825 static void
3826 set_state_reserv (state_t state, int cycle_num, int unit_num)
3828 set_unit_reserv (state->reservs, cycle_num, unit_num);
3831 /* Return nonzero value if the deterministic states contains a
3832 reservation of the same cpu unit on the same cpu cycle. */
3833 static int
3834 intersected_state_reservs_p (state_t state1, state_t state2)
3836 gcc_assert (state1->automaton == state2->automaton);
3837 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3840 /* Return deterministic state (inserted into the table) which
3841 representing the automaton state which is union of reservations of
3842 the deterministic states masked by RESERVS. */
3843 static state_t
3844 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3846 state_t result;
3847 state_t state_in_table;
3849 gcc_assert (state1->automaton == state2->automaton);
3850 result = get_free_state (1, state1->automaton);
3851 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3852 reserv_sets_and (result->reservs, result->reservs, reservs);
3853 state_in_table = insert_state (result);
3854 if (result != state_in_table)
3856 free_state (result);
3857 result = state_in_table;
3859 return result;
3862 /* Return deterministic state (inserted into the table) which
3863 represent the automaton state is obtained from deterministic STATE
3864 by advancing cpu cycle and masking by RESERVS. */
3865 static state_t
3866 state_shift (state_t state, reserv_sets_t reservs)
3868 state_t result;
3869 state_t state_in_table;
3871 result = get_free_state (1, state->automaton);
3872 reserv_sets_shift (result->reservs, state->reservs);
3873 reserv_sets_and (result->reservs, result->reservs, reservs);
3874 state_in_table = insert_state (result);
3875 if (result != state_in_table)
3877 free_state (result);
3878 result = state_in_table;
3880 return result;
3883 /* Initialization of the abstract data. */
3884 static void
3885 initiate_states (void)
3887 decl_t decl;
3888 int i;
3890 if (description->units_num)
3891 units_array = XNEWVEC (unit_decl_t, description->units_num);
3892 else
3893 units_array = 0;
3895 for (i = 0; i < description->decls_num; i++)
3897 decl = description->decls [i];
3898 if (decl->mode == dm_unit)
3899 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3901 max_cycles_num = description->max_insn_reserv_cycles;
3902 els_in_cycle_reserv
3903 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3904 / (sizeof (set_el_t) * CHAR_BIT));
3905 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3906 curr_unique_state_num = 0;
3907 initiate_alt_states ();
3908 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3909 temp_reserv = alloc_empty_reserv_sets ();
3912 /* Finishing work with the abstract data. */
3913 static void
3914 finish_states (void)
3916 free (units_array);
3917 units_array = 0;
3918 htab_delete (state_table);
3919 first_free_state = NULL;
3920 finish_alt_states ();
3925 /* Abstract data `arcs'. */
3927 /* List of free arcs. */
3928 static arc_t first_free_arc;
3930 #ifndef NDEBUG
3931 /* The following variables is maximal number of allocated nodes
3932 `arc'. */
3933 static int allocated_arcs_num = 0;
3934 #endif
3936 /* The function frees node ARC. */
3937 static void
3938 free_arc (arc_t arc)
3940 arc->next_out_arc = first_free_arc;
3941 first_free_arc = arc;
3944 /* The function removes and frees ARC staring from FROM_STATE. */
3945 static void
3946 remove_arc (state_t from_state, arc_t arc)
3948 arc_t prev_arc;
3949 arc_t curr_arc;
3951 gcc_assert (arc);
3952 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3953 curr_arc != NULL;
3954 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3955 if (curr_arc == arc)
3956 break;
3957 gcc_assert (curr_arc);
3958 if (prev_arc == NULL)
3959 from_state->first_out_arc = arc->next_out_arc;
3960 else
3961 prev_arc->next_out_arc = arc->next_out_arc;
3962 from_state->num_out_arcs--;
3963 free_arc (arc);
3966 /* The functions returns arc with given characteristics (or NULL if
3967 the arc does not exist). */
3968 static arc_t
3969 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3971 arc_t arc;
3973 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3974 if (arc->to_state == to_state && arc->insn == insn)
3975 return arc;
3976 return NULL;
3979 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
3980 unless such an arc already exists. */
3981 static void
3982 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3984 arc_t new_arc;
3986 new_arc = find_arc (from_state, to_state, ainsn);
3987 if (new_arc != NULL)
3988 return;
3989 if (first_free_arc == NULL)
3991 #ifndef NDEBUG
3992 allocated_arcs_num++;
3993 #endif
3994 new_arc = XCREATENODE (struct arc);
3995 new_arc->to_state = NULL;
3996 new_arc->insn = NULL;
3997 new_arc->next_out_arc = NULL;
3999 else
4001 new_arc = first_free_arc;
4002 first_free_arc = first_free_arc->next_out_arc;
4004 new_arc->to_state = to_state;
4005 new_arc->insn = ainsn;
4006 ainsn->arc_exists_p = 1;
4007 new_arc->next_out_arc = from_state->first_out_arc;
4008 from_state->first_out_arc = new_arc;
4009 from_state->num_out_arcs++;
4010 new_arc->next_arc_marked_by_insn = NULL;
4013 /* The function returns the first arc starting from STATE. */
4014 static arc_t
4015 first_out_arc (const_state_t state)
4017 return state->first_out_arc;
4020 /* The function returns next out arc after ARC. */
4021 static arc_t
4022 next_out_arc (arc_t arc)
4024 return arc->next_out_arc;
4027 /* Initialization of the abstract data. */
4028 static void
4029 initiate_arcs (void)
4031 first_free_arc = NULL;
4034 /* Finishing work with the abstract data. */
4035 static void
4036 finish_arcs (void)
4042 /* Abstract data `automata lists'. */
4044 /* List of free states. */
4045 static automata_list_el_t first_free_automata_list_el;
4047 /* The list being formed. */
4048 static automata_list_el_t current_automata_list;
4050 /* Hash table of automata lists. */
4051 static htab_t automata_list_table;
4053 /* The following function returns free automata list el. It may be
4054 new allocated node or node freed earlier. */
4055 static automata_list_el_t
4056 get_free_automata_list_el (void)
4058 automata_list_el_t result;
4060 if (first_free_automata_list_el != NULL)
4062 result = first_free_automata_list_el;
4063 first_free_automata_list_el
4064 = first_free_automata_list_el->next_automata_list_el;
4066 else
4067 result = XCREATENODE (struct automata_list_el);
4068 result->automaton = NULL;
4069 result->next_automata_list_el = NULL;
4070 return result;
4073 /* The function frees node AUTOMATA_LIST_EL. */
4074 static void
4075 free_automata_list_el (automata_list_el_t automata_list_el)
4077 if (automata_list_el == NULL)
4078 return;
4079 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4080 first_free_automata_list_el = automata_list_el;
4083 /* The function frees list AUTOMATA_LIST. */
4084 static void
4085 free_automata_list (automata_list_el_t automata_list)
4087 automata_list_el_t curr_automata_list_el;
4088 automata_list_el_t next_automata_list_el;
4090 for (curr_automata_list_el = automata_list;
4091 curr_automata_list_el != NULL;
4092 curr_automata_list_el = next_automata_list_el)
4094 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4095 free_automata_list_el (curr_automata_list_el);
4099 /* Hash value of AUTOMATA_LIST. */
4100 static hashval_t
4101 automata_list_hash (const void *automata_list)
4103 unsigned int hash_value;
4104 const_automata_list_el_t curr_automata_list_el;
4106 hash_value = 0;
4107 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4108 curr_automata_list_el != NULL;
4109 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4110 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4111 | (hash_value << CHAR_BIT))
4112 + curr_automata_list_el->automaton->automaton_order_num);
4113 return hash_value;
4116 /* Return nonzero value if the automata_lists are the same. */
4117 static int
4118 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4120 const_automata_list_el_t automata_list_el_1;
4121 const_automata_list_el_t automata_list_el_2;
4123 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4124 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4125 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4126 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4127 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4128 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4129 return 0;
4130 return automata_list_el_1 == automata_list_el_2;
4133 /* Initialization of the abstract data. */
4134 static void
4135 initiate_automata_lists (void)
4137 first_free_automata_list_el = NULL;
4138 automata_list_table = htab_create (1500, automata_list_hash,
4139 automata_list_eq_p, (htab_del) 0);
4142 /* The following function starts new automata list and makes it the
4143 current one. */
4144 static void
4145 automata_list_start (void)
4147 current_automata_list = NULL;
4150 /* The following function adds AUTOMATON to the current list. */
4151 static void
4152 automata_list_add (automaton_t automaton)
4154 automata_list_el_t el;
4156 el = get_free_automata_list_el ();
4157 el->automaton = automaton;
4158 el->next_automata_list_el = current_automata_list;
4159 current_automata_list = el;
4162 /* The following function finishes forming the current list, inserts
4163 it into the table and returns it. */
4164 static automata_list_el_t
4165 automata_list_finish (void)
4167 void **entry_ptr;
4169 if (current_automata_list == NULL)
4170 return NULL;
4171 entry_ptr = htab_find_slot (automata_list_table,
4172 (void *) current_automata_list, INSERT);
4173 if (*entry_ptr == NULL)
4174 *entry_ptr = (void *) current_automata_list;
4175 else
4176 free_automata_list (current_automata_list);
4177 current_automata_list = NULL;
4178 return (automata_list_el_t) *entry_ptr;
4181 /* Finishing work with the abstract data. */
4182 static void
4183 finish_automata_lists (void)
4185 htab_delete (automata_list_table);
4190 /* The page contains abstract data for work with exclusion sets (see
4191 exclusion_set in file rtl.def). */
4193 /* The following variable refers to an exclusion set returned by
4194 get_excl_set. This is bit string of length equal to cpu units
4195 number. If exclusion set for given unit contains 1 for a unit,
4196 then simultaneous reservation of the units is prohibited. */
4197 static reserv_sets_t excl_set;
4199 /* The array contains exclusion sets for each unit. */
4200 static reserv_sets_t *unit_excl_set_table;
4202 /* The following function forms the array containing exclusion sets
4203 for each unit. */
4204 static void
4205 initiate_excl_sets (void)
4207 decl_t decl;
4208 reserv_sets_t unit_excl_set;
4209 unit_set_el_t el;
4210 int i;
4212 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4213 excl_set = (reserv_sets_t) obstack_base (&irp);
4214 obstack_finish (&irp);
4215 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4216 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4217 obstack_finish (&irp);
4218 /* Evaluate unit exclusion sets. */
4219 for (i = 0; i < description->decls_num; i++)
4221 decl = description->decls [i];
4222 if (decl->mode == dm_unit)
4224 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4225 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4226 obstack_finish (&irp);
4227 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4228 for (el = DECL_UNIT (decl)->excl_list;
4229 el != NULL;
4230 el = el->next_unit_set_el)
4232 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4233 el->unit_decl->in_set_p = TRUE;
4235 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4240 /* The function sets up and return EXCL_SET which is union of
4241 exclusion sets for each unit in IN_SET. */
4242 static reserv_sets_t
4243 get_excl_set (reserv_sets_t in_set)
4245 int el;
4246 unsigned int i;
4247 int start_unit_num;
4248 int unit_num;
4250 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4251 for (el = 0; el < els_in_cycle_reserv; el++)
4252 if (in_set[el])
4253 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4254 if ((in_set[el] >> i) & 1)
4256 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4257 if (start_unit_num >= description->units_num)
4258 return excl_set;
4259 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4261 excl_set [unit_num]
4262 |= unit_excl_set_table [start_unit_num] [unit_num];
4265 return excl_set;
4270 /* The page contains abstract data for work with presence/absence
4271 pattern sets (see presence_set/absence_set in file rtl.def). */
4273 /* The following arrays contain correspondingly presence, final
4274 presence, absence, and final absence patterns for each unit. */
4275 static pattern_reserv_t *unit_presence_set_table;
4276 static pattern_reserv_t *unit_final_presence_set_table;
4277 static pattern_reserv_t *unit_absence_set_table;
4278 static pattern_reserv_t *unit_final_absence_set_table;
4280 /* The following function forms list of reservation sets for given
4281 PATTERN_LIST. */
4282 static pattern_reserv_t
4283 form_reserv_sets_list (pattern_set_el_t pattern_list)
4285 pattern_set_el_t el;
4286 pattern_reserv_t first, curr, prev;
4287 int i;
4289 prev = first = NULL;
4290 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4292 curr = XCREATENODE (struct pattern_reserv);
4293 curr->reserv = alloc_empty_reserv_sets ();
4294 curr->next_pattern_reserv = NULL;
4295 for (i = 0; i < el->units_num; i++)
4297 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4298 el->unit_decls [i]->in_set_p = TRUE;
4300 if (prev != NULL)
4301 prev->next_pattern_reserv = curr;
4302 else
4303 first = curr;
4304 prev = curr;
4306 return first;
4309 /* The following function forms the array containing presence and
4310 absence pattern sets for each unit. */
4311 static void
4312 initiate_presence_absence_pattern_sets (void)
4314 decl_t decl;
4315 int i;
4317 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4318 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4319 obstack_finish (&irp);
4320 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4321 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4322 obstack_finish (&irp);
4323 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4324 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4325 obstack_finish (&irp);
4326 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4327 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4328 obstack_finish (&irp);
4329 /* Evaluate unit presence/absence sets. */
4330 for (i = 0; i < description->decls_num; i++)
4332 decl = description->decls [i];
4333 if (decl->mode == dm_unit)
4335 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4336 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4337 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4338 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4339 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4340 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4341 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4342 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4347 /* The function checks that CHECKED_SET satisfies all presence pattern
4348 sets for units in ORIGINAL_SET. The function returns TRUE if it
4349 is ok. */
4350 static int
4351 check_presence_pattern_sets (reserv_sets_t checked_set,
4352 reserv_sets_t original_set,
4353 int final_p)
4355 int el;
4356 unsigned int i;
4357 int start_unit_num;
4358 int unit_num;
4359 int presence_p;
4360 pattern_reserv_t pat_reserv;
4362 for (el = 0; el < els_in_cycle_reserv; el++)
4363 if (original_set[el])
4364 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4365 if ((original_set[el] >> i) & 1)
4367 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4368 if (start_unit_num >= description->units_num)
4369 break;
4370 if ((final_p
4371 && unit_final_presence_set_table [start_unit_num] == NULL)
4372 || (!final_p
4373 && unit_presence_set_table [start_unit_num] == NULL))
4374 continue;
4375 presence_p = FALSE;
4376 for (pat_reserv = (final_p
4377 ? unit_final_presence_set_table [start_unit_num]
4378 : unit_presence_set_table [start_unit_num]);
4379 pat_reserv != NULL;
4380 pat_reserv = pat_reserv->next_pattern_reserv)
4382 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4383 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4384 != pat_reserv->reserv [unit_num])
4385 break;
4386 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4388 if (!presence_p)
4389 return FALSE;
4391 return TRUE;
4394 /* The function checks that CHECKED_SET satisfies all absence pattern
4395 sets for units in ORIGINAL_SET. The function returns TRUE if it
4396 is ok. */
4397 static int
4398 check_absence_pattern_sets (reserv_sets_t checked_set,
4399 reserv_sets_t original_set,
4400 int final_p)
4402 int el;
4403 unsigned int i;
4404 int start_unit_num;
4405 int unit_num;
4406 pattern_reserv_t pat_reserv;
4408 for (el = 0; el < els_in_cycle_reserv; el++)
4409 if (original_set[el])
4410 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4411 if ((original_set[el] >> i) & 1)
4413 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4414 if (start_unit_num >= description->units_num)
4415 break;
4416 for (pat_reserv = (final_p
4417 ? unit_final_absence_set_table [start_unit_num]
4418 : unit_absence_set_table [start_unit_num]);
4419 pat_reserv != NULL;
4420 pat_reserv = pat_reserv->next_pattern_reserv)
4422 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4423 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4424 != pat_reserv->reserv [unit_num]
4425 && pat_reserv->reserv [unit_num])
4426 break;
4427 if (unit_num >= els_in_cycle_reserv)
4428 return FALSE;
4431 return TRUE;
4436 /* This page contains code for transformation of original reservations
4437 described in .md file. The main goal of transformations is
4438 simplifying reservation and lifting up all `|' on the top of IR
4439 reservation representation. */
4442 /* The following function makes copy of IR representation of
4443 reservation. The function also substitutes all reservations
4444 defined by define_reservation by corresponding value during making
4445 the copy. */
4446 static regexp_t
4447 copy_insn_regexp (regexp_t regexp)
4449 regexp_t result;
4450 int i;
4452 switch (regexp->mode)
4454 case rm_reserv:
4455 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4456 break;
4458 case rm_unit:
4459 result = XCOPYNODE (struct regexp, regexp);
4460 break;
4462 case rm_repeat:
4463 result = XCOPYNODE (struct regexp, regexp);
4464 REGEXP_REPEAT (result)->regexp
4465 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4466 break;
4468 case rm_sequence:
4469 result = XCOPYNODEVAR (struct regexp, regexp,
4470 sizeof (struct regexp) + sizeof (regexp_t)
4471 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4472 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4473 REGEXP_SEQUENCE (result)->regexps [i]
4474 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4475 break;
4477 case rm_allof:
4478 result = XCOPYNODEVAR (struct regexp, regexp,
4479 sizeof (struct regexp) + sizeof (regexp_t)
4480 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4481 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4482 REGEXP_ALLOF (result)->regexps [i]
4483 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4484 break;
4486 case rm_oneof:
4487 result = XCOPYNODEVAR (struct regexp, regexp,
4488 sizeof (struct regexp) + sizeof (regexp_t)
4489 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4490 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4491 REGEXP_ONEOF (result)->regexps [i]
4492 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4493 break;
4495 case rm_nothing:
4496 result = XCOPYNODE (struct regexp, regexp);
4497 break;
4499 default:
4500 gcc_unreachable ();
4502 return result;
4505 /* The following variable is set up 1 if a transformation has been
4506 applied. */
4507 static int regexp_transformed_p;
4509 /* The function makes transformation
4510 A*N -> A, A, ... */
4511 static regexp_t
4512 transform_1 (regexp_t regexp)
4514 int i;
4515 int repeat_num;
4516 regexp_t operand;
4517 pos_t pos;
4519 if (regexp->mode == rm_repeat)
4521 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4522 gcc_assert (repeat_num > 1);
4523 operand = REGEXP_REPEAT (regexp)->regexp;
4524 pos = regexp->mode;
4525 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4526 + sizeof (regexp_t) * (repeat_num - 1));
4527 regexp->mode = rm_sequence;
4528 regexp->pos = pos;
4529 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4530 for (i = 0; i < repeat_num; i++)
4531 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4532 regexp_transformed_p = 1;
4534 return regexp;
4537 /* The function makes transformations
4538 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4539 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4540 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4541 static regexp_t
4542 transform_2 (regexp_t regexp)
4544 if (regexp->mode == rm_sequence)
4546 regexp_t sequence = NULL;
4547 regexp_t result;
4548 int sequence_index = 0;
4549 int i, j;
4551 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4552 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4554 sequence_index = i;
4555 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4556 break;
4558 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4560 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4561 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4562 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4563 + sizeof (regexp_t)
4564 * (REGEXP_SEQUENCE (regexp)->regexps_num
4565 + REGEXP_SEQUENCE (sequence)->regexps_num
4566 - 2));
4567 result->mode = rm_sequence;
4568 result->pos = regexp->pos;
4569 REGEXP_SEQUENCE (result)->regexps_num
4570 = (REGEXP_SEQUENCE (regexp)->regexps_num
4571 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4572 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4573 if (i < sequence_index)
4574 REGEXP_SEQUENCE (result)->regexps [i]
4575 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4576 else if (i > sequence_index)
4577 REGEXP_SEQUENCE (result)->regexps
4578 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4579 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4580 else
4581 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4582 REGEXP_SEQUENCE (result)->regexps [i + j]
4583 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4584 regexp_transformed_p = 1;
4585 regexp = result;
4588 else if (regexp->mode == rm_allof)
4590 regexp_t allof = NULL;
4591 regexp_t result;
4592 int allof_index = 0;
4593 int i, j;
4595 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4596 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4598 allof_index = i;
4599 allof = REGEXP_ALLOF (regexp)->regexps [i];
4600 break;
4602 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4604 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4605 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4606 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4607 + sizeof (regexp_t)
4608 * (REGEXP_ALLOF (regexp)->regexps_num
4609 + REGEXP_ALLOF (allof)->regexps_num - 2));
4610 result->mode = rm_allof;
4611 result->pos = regexp->pos;
4612 REGEXP_ALLOF (result)->regexps_num
4613 = (REGEXP_ALLOF (regexp)->regexps_num
4614 + REGEXP_ALLOF (allof)->regexps_num - 1);
4615 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4616 if (i < allof_index)
4617 REGEXP_ALLOF (result)->regexps [i]
4618 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4619 else if (i > allof_index)
4620 REGEXP_ALLOF (result)->regexps
4621 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4622 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4623 else
4624 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4625 REGEXP_ALLOF (result)->regexps [i + j]
4626 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4627 regexp_transformed_p = 1;
4628 regexp = result;
4631 else if (regexp->mode == rm_oneof)
4633 regexp_t oneof = NULL;
4634 regexp_t result;
4635 int oneof_index = 0;
4636 int i, j;
4638 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4639 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4641 oneof_index = i;
4642 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4643 break;
4645 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4647 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4648 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4649 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4650 + sizeof (regexp_t)
4651 * (REGEXP_ONEOF (regexp)->regexps_num
4652 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4653 result->mode = rm_oneof;
4654 result->pos = regexp->pos;
4655 REGEXP_ONEOF (result)->regexps_num
4656 = (REGEXP_ONEOF (regexp)->regexps_num
4657 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4658 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4659 if (i < oneof_index)
4660 REGEXP_ONEOF (result)->regexps [i]
4661 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4662 else if (i > oneof_index)
4663 REGEXP_ONEOF (result)->regexps
4664 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4665 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4666 else
4667 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4668 REGEXP_ONEOF (result)->regexps [i + j]
4669 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4670 regexp_transformed_p = 1;
4671 regexp = result;
4674 return regexp;
4677 /* The function makes transformations
4678 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4679 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4680 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4681 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4682 static regexp_t
4683 transform_3 (regexp_t regexp)
4685 if (regexp->mode == rm_sequence)
4687 regexp_t oneof = NULL;
4688 int oneof_index = 0;
4689 regexp_t result;
4690 regexp_t sequence;
4691 int i, j;
4693 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4694 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4696 oneof_index = i;
4697 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4698 break;
4700 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4702 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4703 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4704 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4705 + sizeof (regexp_t)
4706 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4707 result->mode = rm_oneof;
4708 result->pos = regexp->pos;
4709 REGEXP_ONEOF (result)->regexps_num
4710 = REGEXP_ONEOF (oneof)->regexps_num;
4711 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4713 sequence
4714 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4715 + sizeof (regexp_t)
4716 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4717 sequence->mode = rm_sequence;
4718 sequence->pos = regexp->pos;
4719 REGEXP_SEQUENCE (sequence)->regexps_num
4720 = REGEXP_SEQUENCE (regexp)->regexps_num;
4721 REGEXP_ONEOF (result)->regexps [i] = sequence;
4722 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4723 if (j != oneof_index)
4724 REGEXP_SEQUENCE (sequence)->regexps [j]
4725 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4726 else
4727 REGEXP_SEQUENCE (sequence)->regexps [j]
4728 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4730 regexp_transformed_p = 1;
4731 regexp = result;
4734 else if (regexp->mode == rm_allof)
4736 regexp_t oneof = NULL;
4737 regexp_t seq;
4738 int oneof_index = 0;
4739 int max_seq_length, allof_length;
4740 regexp_t result;
4741 regexp_t allof = NULL;
4742 regexp_t allof_op = NULL;
4743 int i, j;
4745 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4746 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4748 oneof_index = i;
4749 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4750 break;
4752 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4754 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4755 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4756 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4757 + sizeof (regexp_t)
4758 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4759 result->mode = rm_oneof;
4760 result->pos = regexp->pos;
4761 REGEXP_ONEOF (result)->regexps_num
4762 = REGEXP_ONEOF (oneof)->regexps_num;
4763 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4765 allof
4766 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4767 + sizeof (regexp_t)
4768 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4769 allof->mode = rm_allof;
4770 allof->pos = regexp->pos;
4771 REGEXP_ALLOF (allof)->regexps_num
4772 = REGEXP_ALLOF (regexp)->regexps_num;
4773 REGEXP_ONEOF (result)->regexps [i] = allof;
4774 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4775 if (j != oneof_index)
4776 REGEXP_ALLOF (allof)->regexps [j]
4777 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4778 else
4779 REGEXP_ALLOF (allof)->regexps [j]
4780 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4782 regexp_transformed_p = 1;
4783 regexp = result;
4785 max_seq_length = 0;
4786 if (regexp->mode == rm_allof)
4787 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4789 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4791 case rm_sequence:
4792 seq = REGEXP_ALLOF (regexp)->regexps [i];
4793 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4794 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4795 break;
4797 case rm_unit:
4798 case rm_nothing:
4799 break;
4801 default:
4802 max_seq_length = 0;
4803 goto break_for;
4806 break_for:
4807 if (max_seq_length != 0)
4809 gcc_assert (max_seq_length != 1
4810 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4811 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4812 + sizeof (regexp_t) * (max_seq_length - 1));
4813 result->mode = rm_sequence;
4814 result->pos = regexp->pos;
4815 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4816 for (i = 0; i < max_seq_length; i++)
4818 allof_length = 0;
4819 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4820 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4822 case rm_sequence:
4823 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4824 ->regexps [j])->regexps_num))
4826 allof_op
4827 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4828 ->regexps [j])
4829 ->regexps [i]);
4830 allof_length++;
4832 break;
4833 case rm_unit:
4834 case rm_nothing:
4835 if (i == 0)
4837 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4838 allof_length++;
4840 break;
4841 default:
4842 break;
4845 if (allof_length == 1)
4846 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4847 else
4849 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4850 + sizeof (regexp_t)
4851 * (allof_length - 1));
4852 allof->mode = rm_allof;
4853 allof->pos = regexp->pos;
4854 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4855 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4856 allof_length = 0;
4857 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4858 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4859 && (i <
4860 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4861 ->regexps [j])->regexps_num)))
4863 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4864 ->regexps [j])
4865 ->regexps [i]);
4866 REGEXP_ALLOF (allof)->regexps [allof_length]
4867 = allof_op;
4868 allof_length++;
4870 else if (i == 0
4871 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4872 == rm_unit
4873 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4874 == rm_nothing)))
4876 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4877 REGEXP_ALLOF (allof)->regexps [allof_length]
4878 = allof_op;
4879 allof_length++;
4883 regexp_transformed_p = 1;
4884 regexp = result;
4887 return regexp;
4890 /* The function traverses IR of reservation and applies transformations
4891 implemented by FUNC. */
4892 static regexp_t
4893 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4895 int i;
4897 switch (regexp->mode)
4899 case rm_sequence:
4900 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4901 REGEXP_SEQUENCE (regexp)->regexps [i]
4902 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4903 func);
4904 break;
4906 case rm_allof:
4907 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4908 REGEXP_ALLOF (regexp)->regexps [i]
4909 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4910 break;
4912 case rm_oneof:
4913 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4914 REGEXP_ONEOF (regexp)->regexps [i]
4915 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4916 break;
4918 case rm_repeat:
4919 REGEXP_REPEAT (regexp)->regexp
4920 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4921 break;
4923 case rm_nothing:
4924 case rm_unit:
4925 break;
4927 default:
4928 gcc_unreachable ();
4930 return (*func) (regexp);
4933 /* The function applies all transformations for IR representation of
4934 reservation REGEXP. */
4935 static regexp_t
4936 transform_regexp (regexp_t regexp)
4938 regexp = regexp_transform_func (regexp, transform_1);
4941 regexp_transformed_p = 0;
4942 regexp = regexp_transform_func (regexp, transform_2);
4943 regexp = regexp_transform_func (regexp, transform_3);
4945 while (regexp_transformed_p);
4946 return regexp;
4949 /* The function applies all transformations for reservations of all
4950 insn declarations. */
4951 static void
4952 transform_insn_regexps (void)
4954 decl_t decl;
4955 int i;
4957 transform_time = create_ticker ();
4958 add_advance_cycle_insn_decl ();
4959 if (progress_flag)
4960 fprintf (stderr, "Reservation transformation...");
4961 for (i = 0; i < description->decls_num; i++)
4963 decl = description->decls [i];
4964 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4965 DECL_INSN_RESERV (decl)->transformed_regexp
4966 = transform_regexp (copy_insn_regexp
4967 (DECL_INSN_RESERV (decl)->regexp));
4969 if (progress_flag)
4970 fprintf (stderr, "done\n");
4971 ticker_off (&transform_time);
4976 /* The following variable value is TRUE if the first annotated message
4977 about units to automata distribution has been output. */
4978 static int annotation_message_reported_p;
4980 /* The vector contains all decls which are automata. */
4981 static VEC(decl_t, heap) *automaton_decls;
4983 /* The following structure describes usage of a unit in a reservation. */
4984 struct unit_usage
4986 unit_decl_t unit_decl;
4987 /* The following forms a list of units used on the same cycle in the
4988 same alternative. The list is ordered by the correspdoning unit
4989 declarations and there is no unit declaration duplication in the
4990 list. */
4991 struct unit_usage *next;
4993 typedef struct unit_usage *unit_usage_t;
4995 DEF_VEC_P(unit_usage_t);
4996 DEF_VEC_ALLOC_P(unit_usage_t, heap);
4998 /* Obstack for unit_usage structures. */
4999 static struct obstack unit_usages;
5001 /* VLA for representation of array of pointers to unit usage
5002 structures. There is an element for each combination of
5003 (alternative number, cycle). Unit usages on given cycle in
5004 alternative with given number are referred through element with
5005 index equals to the cycle * number of all alternatives in the
5006 regexp + the alternative number. */
5007 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
5009 /* The following function creates the structure unit_usage for UNIT on
5010 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5011 accessed through cycle_alt_unit_usages. */
5012 static void
5013 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5014 int alt_num)
5016 size_t length;
5017 unit_decl_t unit_decl;
5018 unit_usage_t unit_usage_ptr, curr, prev;
5019 int index;
5021 gcc_assert (regexp && regexp->mode == rm_oneof
5022 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
5023 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5025 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5026 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
5027 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages, 0);
5029 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5030 prev = NULL;
5031 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
5032 curr != NULL;
5033 prev = curr, curr = curr->next)
5034 if (curr->unit_decl >= unit_decl)
5035 break;
5036 if (curr != NULL && curr->unit_decl == unit_decl)
5037 return;
5038 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5039 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5040 obstack_finish (&unit_usages);
5041 unit_usage_ptr->unit_decl = unit_decl;
5042 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5043 unit_usage_ptr->next = curr;
5044 if (prev == NULL)
5045 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
5046 else
5047 prev->next = unit_usage_ptr;
5050 /* Return true if unit UNIT_DECL is present on the LIST. */
5051 static bool
5052 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5054 while (list != NULL)
5056 if (list->unit_decl == unit_decl)
5057 return true;
5058 list = list->next;
5060 return false;
5063 /* The function returns true if reservations of alternatives ALT1 and
5064 ALT2 are equal after excluding reservations of units of
5065 EXCLUDED_AUTOMATON_DECL. */
5066 static bool
5067 equal_alternatives_p (int alt1, int alt2, int n_alts,
5068 struct automaton_decl *excluded_automaton_decl)
5070 int i;
5071 unit_usage_t list1, list2;
5073 for (i = 0;
5074 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5075 i += n_alts)
5077 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5078 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5079 list1 = list1->next, list2 = list2->next)
5081 while (list1 != NULL
5082 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5083 list1 = list1->next;
5084 while (list2 != NULL
5085 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5086 list2 = list2->next;
5087 if (list1 == NULL || list2 == NULL)
5089 if (list1 != list2)
5090 return false;
5091 else
5092 break;
5094 if (list1->unit_decl != list2->unit_decl)
5095 return false;
5098 return true;
5101 DEF_VEC_I(int);
5102 DEF_VEC_ALLOC_I(int, heap);
5104 /* The function processes given REGEXP to find units with the wrong
5105 distribution. */
5106 static void
5107 check_regexp_units_distribution (const char *insn_reserv_name,
5108 regexp_t regexp)
5110 int i, j, k, cycle, start, n_alts, alt, alt2;
5111 bool annotation_reservation_message_reported_p;
5112 regexp_t seq, allof, unit;
5113 struct unit_usage *unit_usage_ptr;
5114 VEC(int, heap) *marked;
5116 if (regexp == NULL || regexp->mode != rm_oneof)
5117 return;
5118 /* Store all unit usages in the regexp: */
5119 obstack_init (&unit_usages);
5120 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5122 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5124 seq = REGEXP_ONEOF (regexp)->regexps [i];
5125 switch (seq->mode)
5127 case rm_sequence:
5128 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5130 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5131 switch (allof->mode)
5133 case rm_allof:
5134 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5136 unit = REGEXP_ALLOF (allof)->regexps [k];
5137 if (unit->mode == rm_unit)
5138 store_alt_unit_usage (regexp, unit, j, i);
5139 else
5140 gcc_assert (unit->mode == rm_nothing);
5142 break;
5144 case rm_unit:
5145 store_alt_unit_usage (regexp, allof, j, i);
5146 break;
5148 case rm_nothing:
5149 break;
5151 default:
5152 gcc_unreachable ();
5155 break;
5157 case rm_allof:
5158 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5160 unit = REGEXP_ALLOF (seq)->regexps [k];
5161 switch (unit->mode)
5163 case rm_unit:
5164 store_alt_unit_usage (regexp, unit, 0, i);
5165 break;
5167 case rm_nothing:
5168 break;
5170 default:
5171 gcc_unreachable ();
5174 break;
5176 case rm_unit:
5177 store_alt_unit_usage (regexp, seq, 0, i);
5178 break;
5180 case rm_nothing:
5181 break;
5183 default:
5184 gcc_unreachable ();
5187 /* Check distribution: */
5188 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5189 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5190 unit_usage_ptr != NULL;
5191 unit_usage_ptr = unit_usage_ptr->next)
5192 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5193 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5194 marked = VEC_alloc (int, heap, n_alts);
5195 for (i = 0; i < n_alts; i++)
5196 VEC_safe_push (int, heap, marked, 0);
5197 annotation_reservation_message_reported_p = false;
5198 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5200 cycle = i / n_alts;
5201 start = cycle * n_alts;
5202 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5203 unit_usage_ptr != NULL;
5204 unit_usage_ptr = unit_usage_ptr->next)
5206 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5207 continue;
5208 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5209 for (alt = 0; alt < n_alts; alt++)
5210 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5211 cycle_alt_unit_usages,
5212 start + alt),
5213 unit_usage_ptr->unit_decl))
5214 break;
5215 if (alt >= n_alts)
5216 continue;
5217 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5218 for (alt = 0; alt < n_alts; alt++)
5220 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5221 cycle_alt_unit_usages,
5222 start + alt),
5223 unit_usage_ptr->unit_decl))
5224 continue;
5225 for (j = 0;
5226 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5227 j++)
5229 alt2 = j % n_alts;
5230 if (! unit_present_on_list_p
5231 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5232 start + alt2),
5233 unit_usage_ptr->unit_decl)
5234 && equal_alternatives_p (alt, alt2, n_alts,
5235 unit_usage_ptr
5236 ->unit_decl->automaton_decl))
5238 VEC_replace (int, marked, alt, 1);
5239 VEC_replace (int, marked, alt2, 1);
5243 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5245 if (alt < n_alts && 0)
5247 if (! annotation_message_reported_p)
5249 fprintf (stderr, "\n");
5250 error ("The following units do not satisfy units-automata distribution rule");
5251 error ("(Unit presence on one alt and its absence on other alt\n");
5252 error (" result in different other automata reservations)");
5253 annotation_message_reported_p = TRUE;
5255 if (! annotation_reservation_message_reported_p)
5257 error ("Reserv %s:", insn_reserv_name);
5258 annotation_reservation_message_reported_p = true;
5260 error (" Unit %s, cycle %d, alt %d, another alt %d",
5261 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5265 VEC_free (int, heap, marked);
5266 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5267 obstack_free (&unit_usages, NULL);
5270 /* The function finds units which violates units to automata
5271 distribution rule. If the units exist, report about them. */
5272 static void
5273 check_unit_distributions_to_automata (void)
5275 decl_t decl;
5276 int i;
5278 if (progress_flag)
5279 fprintf (stderr, "Check unit distributions to automata...");
5280 automaton_decls = NULL;
5281 for (i = 0; i < description->decls_num; i++)
5283 decl = description->decls [i];
5284 if (decl->mode == dm_automaton)
5285 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5287 if (VEC_length (decl_t, automaton_decls) > 1)
5289 annotation_message_reported_p = FALSE;
5290 for (i = 0; i < description->decls_num; i++)
5292 decl = description->decls [i];
5293 if (decl->mode == dm_insn_reserv)
5294 check_regexp_units_distribution
5295 (DECL_INSN_RESERV (decl)->name,
5296 DECL_INSN_RESERV (decl)->transformed_regexp);
5299 VEC_free (decl_t, heap, automaton_decls);
5300 if (progress_flag)
5301 fprintf (stderr, "done\n");
5306 /* The page contains code for building alt_states (see comments for
5307 IR) describing all possible insns reservations of an automaton. */
5309 /* Current state being formed for which the current alt_state
5310 refers. */
5311 static state_t state_being_formed;
5313 /* Current alt_state being formed. */
5314 static alt_state_t alt_state_being_formed;
5316 /* This recursive function processes `,' and units in reservation
5317 REGEXP for forming alt_states of AUTOMATON. It is believed that
5318 CURR_CYCLE is start cycle of all reservation REGEXP. */
5319 static int
5320 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5321 int curr_cycle)
5323 int i;
5325 if (regexp == NULL)
5326 return curr_cycle;
5328 switch (regexp->mode)
5330 case rm_unit:
5331 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5332 == automaton->automaton_order_num)
5333 set_state_reserv (state_being_formed, curr_cycle,
5334 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5335 return curr_cycle;
5337 case rm_sequence:
5338 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5339 curr_cycle
5340 = process_seq_for_forming_states
5341 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5342 return curr_cycle;
5344 case rm_allof:
5346 int finish_cycle = 0;
5347 int cycle;
5349 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5351 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5352 ->regexps [i],
5353 automaton, curr_cycle);
5354 if (finish_cycle < cycle)
5355 finish_cycle = cycle;
5357 return finish_cycle;
5360 case rm_nothing:
5361 return curr_cycle;
5363 default:
5364 gcc_unreachable ();
5368 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5369 inserts alt_state into the table. */
5370 static void
5371 finish_forming_alt_state (alt_state_t alt_state,
5372 automaton_t automaton ATTRIBUTE_UNUSED)
5374 state_t state_in_table;
5375 state_t corresponding_state;
5377 corresponding_state = alt_state->state;
5378 state_in_table = insert_state (corresponding_state);
5379 if (state_in_table != corresponding_state)
5381 free_state (corresponding_state);
5382 alt_state->state = state_in_table;
5386 /* The following variable value is current automaton insn for whose
5387 reservation the alt states are created. */
5388 static ainsn_t curr_ainsn;
5390 /* This recursive function processes `|' in reservation REGEXP for
5391 forming alt_states of AUTOMATON. List of the alt states should
5392 have the same order as in the description. */
5393 static void
5394 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5395 int inside_oneof_p)
5397 int i;
5399 if (regexp->mode != rm_oneof)
5401 alt_state_being_formed = get_free_alt_state ();
5402 state_being_formed = get_free_state (1, automaton);
5403 alt_state_being_formed->state = state_being_formed;
5404 /* We inserts in reverse order but we process alternatives also
5405 in reverse order. So we have the same order of alternative
5406 as in the description. */
5407 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5408 curr_ainsn->alt_states = alt_state_being_formed;
5409 (void) process_seq_for_forming_states (regexp, automaton, 0);
5410 finish_forming_alt_state (alt_state_being_formed, automaton);
5412 else
5414 gcc_assert (!inside_oneof_p);
5415 /* We processes it in reverse order to get list with the same
5416 order as in the description. See also the previous
5417 commentary. */
5418 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5419 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5420 automaton, 1);
5424 /* Create nodes alt_state for all AUTOMATON insns. */
5425 static void
5426 create_alt_states (automaton_t automaton)
5428 struct insn_reserv_decl *reserv_decl;
5430 for (curr_ainsn = automaton->ainsn_list;
5431 curr_ainsn != NULL;
5432 curr_ainsn = curr_ainsn->next_ainsn)
5434 reserv_decl = curr_ainsn->insn_reserv_decl;
5435 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5437 curr_ainsn->alt_states = NULL;
5438 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5439 automaton, 0);
5440 curr_ainsn->sorted_alt_states
5441 = uniq_sort_alt_states (curr_ainsn->alt_states);
5448 /* The page contains major code for building DFA(s) for fast pipeline
5449 hazards recognition. */
5451 /* The function forms list of ainsns of AUTOMATON with the same
5452 reservation. */
5454 static void
5455 form_ainsn_with_same_reservs (automaton_t automaton)
5457 ainsn_t curr_ainsn;
5458 size_t i;
5459 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5461 for (curr_ainsn = automaton->ainsn_list;
5462 curr_ainsn != NULL;
5463 curr_ainsn = curr_ainsn->next_ainsn)
5464 if (curr_ainsn->insn_reserv_decl
5465 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5467 curr_ainsn->next_same_reservs_insn = NULL;
5468 curr_ainsn->first_insn_with_same_reservs = 1;
5470 else
5472 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5473 if (alt_states_eq
5474 (curr_ainsn->sorted_alt_states,
5475 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5476 break;
5477 curr_ainsn->next_same_reservs_insn = NULL;
5478 if (i < VEC_length (ainsn_t, last_insns))
5480 curr_ainsn->first_insn_with_same_reservs = 0;
5481 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5482 = curr_ainsn;
5483 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5485 else
5487 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5488 curr_ainsn->first_insn_with_same_reservs = 1;
5491 VEC_free (ainsn_t, heap, last_insns);
5494 /* Forming unit reservations which can affect creating the automaton
5495 states achieved from a given state. It permits to build smaller
5496 automata in many cases. We would have the same automata after
5497 the minimization without such optimization, but the automaton
5498 right after the building could be huge. So in other words, usage
5499 of reservs_matter means some minimization during building the
5500 automaton. */
5501 static reserv_sets_t
5502 form_reservs_matter (automaton_t automaton)
5504 int cycle, unit;
5505 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5507 for (cycle = 0; cycle < max_cycles_num; cycle++)
5508 for (unit = 0; unit < description->units_num; unit++)
5509 if (units_array [unit]->automaton_decl
5510 == automaton->corresponding_automaton_decl
5511 && (cycle >= units_array [unit]->min_occ_cycle_num
5512 /* We can not remove queried unit from reservations. */
5513 || units_array [unit]->query_p
5514 /* We can not remove units which are used
5515 `exclusion_set', `presence_set',
5516 `final_presence_set', `absence_set', and
5517 `final_absence_set'. */
5518 || units_array [unit]->in_set_p))
5519 set_unit_reserv (reservs_matter, cycle, unit);
5520 return reservs_matter;
5523 /* The following function creates all states of nondeterministic AUTOMATON. */
5524 static void
5525 make_automaton (automaton_t automaton)
5527 ainsn_t ainsn;
5528 struct insn_reserv_decl *insn_reserv_decl;
5529 alt_state_t alt_state;
5530 state_t state;
5531 state_t start_state;
5532 state_t state2;
5533 ainsn_t advance_cycle_ainsn;
5534 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5535 int states_n;
5536 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5538 /* Create the start state (empty state). */
5539 start_state = insert_state (get_free_state (1, automaton));
5540 automaton->start_state = start_state;
5541 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5542 VEC_safe_push (state_t, heap, state_stack, start_state);
5543 states_n = 1;
5544 while (VEC_length (state_t, state_stack) != 0)
5546 state = VEC_pop (state_t, state_stack);
5547 advance_cycle_ainsn = NULL;
5548 for (ainsn = automaton->ainsn_list;
5549 ainsn != NULL;
5550 ainsn = ainsn->next_ainsn)
5551 if (ainsn->first_insn_with_same_reservs)
5553 insn_reserv_decl = ainsn->insn_reserv_decl;
5554 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5556 /* We process alt_states in the same order as they are
5557 present in the description. */
5558 for (alt_state = ainsn->alt_states;
5559 alt_state != NULL;
5560 alt_state = alt_state->next_alt_state)
5562 state2 = alt_state->state;
5563 if (!intersected_state_reservs_p (state, state2))
5565 state2 = states_union (state, state2, reservs_matter);
5566 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5568 state2->it_was_placed_in_stack_for_NDFA_forming
5569 = 1;
5570 VEC_safe_push (state_t, heap, state_stack, state2);
5571 states_n++;
5572 if (progress_flag && states_n % 100 == 0)
5573 fprintf (stderr, ".");
5575 add_arc (state, state2, ainsn);
5576 if (!ndfa_flag)
5577 break;
5581 else
5582 advance_cycle_ainsn = ainsn;
5584 /* Add transition to advance cycle. */
5585 state2 = state_shift (state, reservs_matter);
5586 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5588 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5589 VEC_safe_push (state_t, heap, state_stack, state2);
5590 states_n++;
5591 if (progress_flag && states_n % 100 == 0)
5592 fprintf (stderr, ".");
5594 gcc_assert (advance_cycle_ainsn);
5595 add_arc (state, state2, advance_cycle_ainsn);
5597 VEC_free (state_t, heap, state_stack);
5600 /* Form lists of all arcs of STATE marked by the same ainsn. */
5601 static void
5602 form_arcs_marked_by_insn (state_t state)
5604 decl_t decl;
5605 arc_t arc;
5606 int i;
5608 for (i = 0; i < description->decls_num; i++)
5610 decl = description->decls [i];
5611 if (decl->mode == dm_insn_reserv)
5612 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5614 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5616 gcc_assert (arc->insn);
5617 arc->next_arc_marked_by_insn
5618 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5619 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5623 /* The function creates composed state (see comments for IR) from
5624 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5625 same insn. If the composed state is not in STATE_STACK yet, it is
5626 pushed into STATE_STACK. */
5628 static int
5629 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5630 VEC(state_t, heap) **state_stack)
5632 state_t state;
5633 alt_state_t alt_state, curr_alt_state;
5634 alt_state_t new_alt_state;
5635 arc_t curr_arc;
5636 arc_t next_arc;
5637 state_t state_in_table;
5638 state_t temp_state;
5639 alt_state_t canonical_alt_states_list;
5640 int alts_number;
5641 int new_state_p = 0;
5643 if (arcs_marked_by_insn == NULL)
5644 return new_state_p;
5645 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5646 state = arcs_marked_by_insn->to_state;
5647 else
5649 gcc_assert (ndfa_flag);
5650 /* Create composed state. */
5651 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5652 curr_alt_state = NULL;
5653 for (curr_arc = arcs_marked_by_insn;
5654 curr_arc != NULL;
5655 curr_arc = curr_arc->next_arc_marked_by_insn)
5656 if (curr_arc->to_state->component_states == NULL)
5658 new_alt_state = get_free_alt_state ();
5659 new_alt_state->next_alt_state = curr_alt_state;
5660 new_alt_state->state = curr_arc->to_state;
5661 curr_alt_state = new_alt_state;
5663 else
5664 for (alt_state = curr_arc->to_state->component_states;
5665 alt_state != NULL;
5666 alt_state = alt_state->next_sorted_alt_state)
5668 new_alt_state = get_free_alt_state ();
5669 new_alt_state->next_alt_state = curr_alt_state;
5670 new_alt_state->state = alt_state->state;
5671 gcc_assert (!alt_state->state->component_states);
5672 curr_alt_state = new_alt_state;
5674 /* There are not identical sets in the alt state list. */
5675 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5676 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5678 temp_state = state;
5679 state = canonical_alt_states_list->state;
5680 free_state (temp_state);
5682 else
5684 state->component_states = canonical_alt_states_list;
5685 state_in_table = insert_state (state);
5686 if (state_in_table != state)
5688 gcc_assert
5689 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5690 free_state (state);
5691 state = state_in_table;
5693 else
5695 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5696 new_state_p = 1;
5697 for (curr_alt_state = state->component_states;
5698 curr_alt_state != NULL;
5699 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5700 for (curr_arc = first_out_arc (curr_alt_state->state);
5701 curr_arc != NULL;
5702 curr_arc = next_out_arc (curr_arc))
5703 add_arc (state, curr_arc->to_state, curr_arc->insn);
5705 arcs_marked_by_insn->to_state = state;
5706 for (alts_number = 0,
5707 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5708 curr_arc != NULL;
5709 curr_arc = next_arc)
5711 next_arc = curr_arc->next_arc_marked_by_insn;
5712 remove_arc (original_state, curr_arc);
5713 alts_number++;
5717 if (!state->it_was_placed_in_stack_for_DFA_forming)
5719 state->it_was_placed_in_stack_for_DFA_forming = 1;
5720 VEC_safe_push (state_t, heap, *state_stack, state);
5722 return new_state_p;
5725 /* The function transforms nondeterministic AUTOMATON into
5726 deterministic. */
5728 static void
5729 NDFA_to_DFA (automaton_t automaton)
5731 state_t start_state;
5732 state_t state;
5733 decl_t decl;
5734 VEC(state_t, heap) *state_stack;
5735 int i;
5736 int states_n;
5738 state_stack = VEC_alloc (state_t, heap, 0);
5740 /* Create the start state (empty state). */
5741 start_state = automaton->start_state;
5742 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5743 VEC_safe_push (state_t, heap, state_stack, start_state);
5744 states_n = 1;
5745 while (VEC_length (state_t, state_stack) != 0)
5747 state = VEC_pop (state_t, state_stack);
5748 form_arcs_marked_by_insn (state);
5749 for (i = 0; i < description->decls_num; i++)
5751 decl = description->decls [i];
5752 if (decl->mode == dm_insn_reserv
5753 && create_composed_state
5754 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5755 &state_stack))
5757 states_n++;
5758 if (progress_flag && states_n % 100 == 0)
5759 fprintf (stderr, ".");
5763 VEC_free (state_t, heap, state_stack);
5766 /* The following variable value is current number (1, 2, ...) of passing
5767 graph of states. */
5768 static int curr_state_graph_pass_num;
5770 /* This recursive function passes all states achieved from START_STATE
5771 and applies APPLIED_FUNC to them. */
5772 static void
5773 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5775 arc_t arc;
5777 if (start_state->pass_num == curr_state_graph_pass_num)
5778 return;
5779 start_state->pass_num = curr_state_graph_pass_num;
5780 (*applied_func) (start_state);
5781 for (arc = first_out_arc (start_state);
5782 arc != NULL;
5783 arc = next_out_arc (arc))
5784 pass_state_graph (arc->to_state, applied_func);
5787 /* This recursive function passes all states of AUTOMATON and applies
5788 APPLIED_FUNC to them. */
5789 static void
5790 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5792 curr_state_graph_pass_num++;
5793 pass_state_graph (automaton->start_state, applied_func);
5796 /* The function initializes code for passing of all states. */
5797 static void
5798 initiate_pass_states (void)
5800 curr_state_graph_pass_num = 0;
5803 /* The following vla is used for storing pointers to all achieved
5804 states. */
5805 static VEC(state_t, heap) *all_achieved_states;
5807 /* This function is called by function pass_states to add an achieved
5808 STATE. */
5809 static void
5810 add_achieved_state (state_t state)
5812 VEC_safe_push (state_t, heap, all_achieved_states, state);
5815 /* The function sets up equivalence numbers of insns which mark all
5816 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5817 nonzero value) or by equiv_class_num_2 of the destination state.
5818 The function returns number of out arcs of STATE. */
5819 static void
5820 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5822 arc_t arc;
5824 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5826 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5827 arc->insn->insn_reserv_decl->equiv_class_num
5828 = (odd_iteration_flag
5829 ? arc->to_state->equiv_class_num_1
5830 : arc->to_state->equiv_class_num_2);
5831 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5835 /* The function clears equivalence numbers and alt_states in all insns
5836 which mark all out arcs of STATE. */
5837 static void
5838 clear_arc_insns_equiv_num (state_t state)
5840 arc_t arc;
5842 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5843 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5847 /* The following function returns TRUE if STATE reserves the unit with
5848 UNIT_NUM on the first cycle. */
5849 static int
5850 first_cycle_unit_presence (state_t state, int unit_num)
5852 alt_state_t alt_state;
5854 if (state->component_states == NULL)
5855 return test_unit_reserv (state->reservs, 0, unit_num);
5856 else
5858 for (alt_state = state->component_states;
5859 alt_state != NULL;
5860 alt_state = alt_state->next_sorted_alt_state)
5861 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5862 return true;
5864 return false;
5867 /* This fills in the presence_signature[] member of STATE. */
5868 static void
5869 cache_presence (state_t state)
5871 int i, num = 0;
5872 unsigned int sz;
5873 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5874 / (sizeof (int) * CHAR_BIT);
5876 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5877 for (i = 0; i < description->units_num; i++)
5878 if (units_array [i]->query_p)
5880 int presence1_p = first_cycle_unit_presence (state, i);
5881 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5882 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5883 num++;
5887 /* The function returns nonzero value if STATE is not equivalent to
5888 ANOTHER_STATE from the same current partition on equivalence
5889 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5890 output arcs. Iteration of making equivalence partition is defined
5891 by ODD_ITERATION_FLAG. */
5892 static int
5893 state_is_differed (state_t state, state_t another_state,
5894 int odd_iteration_flag)
5896 arc_t arc;
5897 unsigned int sz, si;
5899 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5901 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5902 / (sizeof (int) * CHAR_BIT);
5904 for (si = 0; si < sz; si++)
5905 gcc_assert (state->presence_signature[si]
5906 == another_state->presence_signature[si]);
5908 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5910 if ((odd_iteration_flag
5911 ? arc->to_state->equiv_class_num_1
5912 : arc->to_state->equiv_class_num_2)
5913 != arc->insn->insn_reserv_decl->equiv_class_num)
5914 return 1;
5917 return 0;
5920 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5921 and return -1, 0 or 1. This function can be used as predicate for
5922 qsort(). It requires the member presence_signature[] of both
5923 states be filled. */
5924 static int
5925 compare_states_for_equiv (const void *state_ptr_1,
5926 const void *state_ptr_2)
5928 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5929 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5930 unsigned int sz, si;
5931 if (s1->num_out_arcs < s2->num_out_arcs)
5932 return -1;
5933 else if (s1->num_out_arcs > s2->num_out_arcs)
5934 return 1;
5936 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5937 / (sizeof (int) * CHAR_BIT);
5939 for (si = 0; si < sz; si++)
5940 if (s1->presence_signature[si] < s2->presence_signature[si])
5941 return -1;
5942 else if (s1->presence_signature[si] > s2->presence_signature[si])
5943 return 1;
5944 return 0;
5947 /* The function makes initial partition of STATES on equivalent
5948 classes and saves it into *CLASSES. This function requires the input
5949 to be sorted via compare_states_for_equiv(). */
5950 static int
5951 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
5953 size_t i;
5954 state_t prev = 0;
5955 int class_num = 1;
5957 *classes = VEC_alloc (state_t, heap, 150);
5958 for (i = 0; i < VEC_length (state_t, states); i++)
5960 state_t state = VEC_index (state_t, states, i);
5961 if (prev)
5963 if (compare_states_for_equiv (&prev, &state) != 0)
5965 VEC_safe_push (state_t, heap, *classes, prev);
5966 class_num++;
5967 prev = NULL;
5970 state->equiv_class_num_1 = class_num;
5971 state->next_equiv_class_state = prev;
5972 prev = state;
5974 if (prev)
5975 VEC_safe_push (state_t, heap, *classes, prev);
5976 return class_num;
5979 /* The function copies pointers to equivalent states from vla FROM
5980 into vla TO. */
5981 static void
5982 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
5984 VEC_free (state_t, heap, *to);
5985 *to = VEC_copy (state_t, heap, from);
5988 /* The function processes equivalence class given by its first state,
5989 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5990 are not equivalent states, the function partitions the class
5991 removing nonequivalent states and placing them in
5992 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5993 assigns it to the state equivalence number. If the class has been
5994 partitioned, the function returns nonzero value. */
5995 static int
5996 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5997 VEC(state_t, heap) **next_iteration_classes,
5998 int *new_equiv_class_num_ptr)
6000 state_t new_equiv_class;
6001 int partition_p;
6002 state_t curr_state;
6003 state_t prev_state;
6004 state_t next_state;
6006 partition_p = 0;
6008 while (first_state != NULL)
6010 new_equiv_class = NULL;
6011 if (first_state->next_equiv_class_state != NULL)
6013 /* There are more one states in the class equivalence. */
6014 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6015 for (prev_state = first_state,
6016 curr_state = first_state->next_equiv_class_state;
6017 curr_state != NULL;
6018 curr_state = next_state)
6020 next_state = curr_state->next_equiv_class_state;
6021 if (state_is_differed (curr_state, first_state,
6022 odd_iteration_flag))
6024 /* Remove curr state from the class equivalence. */
6025 prev_state->next_equiv_class_state = next_state;
6026 /* Add curr state to the new class equivalence. */
6027 curr_state->next_equiv_class_state = new_equiv_class;
6028 if (new_equiv_class == NULL)
6029 (*new_equiv_class_num_ptr)++;
6030 if (odd_iteration_flag)
6031 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6032 else
6033 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6034 new_equiv_class = curr_state;
6035 partition_p = 1;
6037 else
6038 prev_state = curr_state;
6040 clear_arc_insns_equiv_num (first_state);
6042 if (new_equiv_class != NULL)
6043 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
6044 first_state = new_equiv_class;
6046 return partition_p;
6049 /* The function finds equivalent states of AUTOMATON. */
6050 static void
6051 evaluate_equiv_classes (automaton_t automaton,
6052 VEC(state_t, heap) **equiv_classes)
6054 int new_equiv_class_num;
6055 int odd_iteration_flag;
6056 int finish_flag;
6057 VEC (state_t, heap) *next_iteration_classes;
6058 size_t i;
6060 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6061 pass_states (automaton, add_achieved_state);
6062 pass_states (automaton, cache_presence);
6063 VEC_qsort (state_t, all_achieved_states, compare_states_for_equiv);
6065 odd_iteration_flag = 0;
6066 new_equiv_class_num = init_equiv_class (all_achieved_states,
6067 &next_iteration_classes);
6071 odd_iteration_flag = !odd_iteration_flag;
6072 finish_flag = 1;
6073 copy_equiv_class (equiv_classes, next_iteration_classes);
6075 /* Transfer equiv numbers for the next iteration. */
6076 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6077 if (odd_iteration_flag)
6078 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6079 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6080 else
6081 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6082 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6084 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6085 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6086 odd_iteration_flag,
6087 &next_iteration_classes,
6088 &new_equiv_class_num))
6089 finish_flag = 0;
6091 while (!finish_flag);
6092 VEC_free (state_t, heap, next_iteration_classes);
6093 VEC_free (state_t, heap, all_achieved_states);
6096 /* The function merges equivalent states of AUTOMATON. */
6097 static void
6098 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6100 state_t curr_state;
6101 state_t new_state;
6102 state_t first_class_state;
6103 alt_state_t alt_states;
6104 alt_state_t alt_state, new_alt_state;
6105 arc_t curr_arc;
6106 arc_t next_arc;
6107 size_t i;
6109 /* Create states corresponding to equivalence classes containing two
6110 or more states. */
6111 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6113 curr_state = VEC_index (state_t, equiv_classes, i);
6114 if (curr_state->next_equiv_class_state != NULL)
6116 /* There are more one states in the class equivalence. */
6117 /* Create new compound state. */
6118 new_state = get_free_state (0, automaton);
6119 alt_states = NULL;
6120 first_class_state = curr_state;
6121 for (curr_state = first_class_state;
6122 curr_state != NULL;
6123 curr_state = curr_state->next_equiv_class_state)
6125 curr_state->equiv_class_state = new_state;
6126 if (curr_state->component_states == NULL)
6128 new_alt_state = get_free_alt_state ();
6129 new_alt_state->state = curr_state;
6130 new_alt_state->next_alt_state = alt_states;
6131 alt_states = new_alt_state;
6133 else
6134 for (alt_state = curr_state->component_states;
6135 alt_state != NULL;
6136 alt_state = alt_state->next_sorted_alt_state)
6138 new_alt_state = get_free_alt_state ();
6139 new_alt_state->state = alt_state->state;
6140 new_alt_state->next_alt_state = alt_states;
6141 alt_states = new_alt_state;
6144 /* Its is important that alt states were sorted before and
6145 after merging to have the same querying results. */
6146 new_state->component_states = uniq_sort_alt_states (alt_states);
6148 else
6149 curr_state->equiv_class_state = curr_state;
6152 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6154 curr_state = VEC_index (state_t, equiv_classes, i);
6155 if (curr_state->next_equiv_class_state != NULL)
6157 first_class_state = curr_state;
6158 /* Create new arcs output from the state corresponding to
6159 equiv class. */
6160 for (curr_arc = first_out_arc (first_class_state);
6161 curr_arc != NULL;
6162 curr_arc = next_out_arc (curr_arc))
6163 add_arc (first_class_state->equiv_class_state,
6164 curr_arc->to_state->equiv_class_state,
6165 curr_arc->insn);
6166 /* Delete output arcs from states of given class equivalence. */
6167 for (curr_state = first_class_state;
6168 curr_state != NULL;
6169 curr_state = curr_state->next_equiv_class_state)
6171 if (automaton->start_state == curr_state)
6172 automaton->start_state = curr_state->equiv_class_state;
6173 /* Delete the state and its output arcs. */
6174 for (curr_arc = first_out_arc (curr_state);
6175 curr_arc != NULL;
6176 curr_arc = next_arc)
6178 next_arc = next_out_arc (curr_arc);
6179 free_arc (curr_arc);
6183 else
6185 /* Change `to_state' of arcs output from the state of given
6186 equivalence class. */
6187 for (curr_arc = first_out_arc (curr_state);
6188 curr_arc != NULL;
6189 curr_arc = next_out_arc (curr_arc))
6190 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6195 /* The function sets up new_cycle_p for states if there is arc to the
6196 state marked by advance_cycle_insn_decl. */
6197 static void
6198 set_new_cycle_flags (state_t state)
6200 arc_t arc;
6202 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6203 if (arc->insn->insn_reserv_decl
6204 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6205 arc->to_state->new_cycle_p = 1;
6208 /* The top level function for minimization of deterministic
6209 AUTOMATON. */
6210 static void
6211 minimize_DFA (automaton_t automaton)
6213 VEC(state_t, heap) *equiv_classes = 0;
6215 evaluate_equiv_classes (automaton, &equiv_classes);
6216 merge_states (automaton, equiv_classes);
6217 pass_states (automaton, set_new_cycle_flags);
6219 VEC_free (state_t, heap, equiv_classes);
6222 /* Values of two variables are counted number of states and arcs in an
6223 automaton. */
6224 static int curr_counted_states_num;
6225 static int curr_counted_arcs_num;
6227 /* The function is called by function `pass_states' to count states
6228 and arcs of an automaton. */
6229 static void
6230 incr_states_and_arcs_nums (state_t state)
6232 arc_t arc;
6234 curr_counted_states_num++;
6235 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6236 curr_counted_arcs_num++;
6239 /* The function counts states and arcs of AUTOMATON. */
6240 static void
6241 count_states_and_arcs (automaton_t automaton, int *states_num,
6242 int *arcs_num)
6244 curr_counted_states_num = 0;
6245 curr_counted_arcs_num = 0;
6246 pass_states (automaton, incr_states_and_arcs_nums);
6247 *states_num = curr_counted_states_num;
6248 *arcs_num = curr_counted_arcs_num;
6251 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6252 recognition after checking and simplifying IR of the
6253 description. */
6254 static void
6255 build_automaton (automaton_t automaton)
6257 int states_num;
6258 int arcs_num;
6260 ticker_on (&NDFA_time);
6261 if (progress_flag)
6263 if (automaton->corresponding_automaton_decl == NULL)
6264 fprintf (stderr, "Create anonymous automaton");
6265 else
6266 fprintf (stderr, "Create automaton `%s'",
6267 automaton->corresponding_automaton_decl->name);
6268 fprintf (stderr, " (1 dot is 100 new states):");
6270 make_automaton (automaton);
6271 if (progress_flag)
6272 fprintf (stderr, " done\n");
6273 ticker_off (&NDFA_time);
6274 count_states_and_arcs (automaton, &states_num, &arcs_num);
6275 automaton->NDFA_states_num = states_num;
6276 automaton->NDFA_arcs_num = arcs_num;
6277 ticker_on (&NDFA_to_DFA_time);
6278 if (progress_flag)
6280 if (automaton->corresponding_automaton_decl == NULL)
6281 fprintf (stderr, "Make anonymous DFA");
6282 else
6283 fprintf (stderr, "Make DFA `%s'",
6284 automaton->corresponding_automaton_decl->name);
6285 fprintf (stderr, " (1 dot is 100 new states):");
6287 NDFA_to_DFA (automaton);
6288 if (progress_flag)
6289 fprintf (stderr, " done\n");
6290 ticker_off (&NDFA_to_DFA_time);
6291 count_states_and_arcs (automaton, &states_num, &arcs_num);
6292 automaton->DFA_states_num = states_num;
6293 automaton->DFA_arcs_num = arcs_num;
6294 if (!no_minimization_flag)
6296 ticker_on (&minimize_time);
6297 if (progress_flag)
6299 if (automaton->corresponding_automaton_decl == NULL)
6300 fprintf (stderr, "Minimize anonymous DFA...");
6301 else
6302 fprintf (stderr, "Minimize DFA `%s'...",
6303 automaton->corresponding_automaton_decl->name);
6305 minimize_DFA (automaton);
6306 if (progress_flag)
6307 fprintf (stderr, "done\n");
6308 ticker_off (&minimize_time);
6309 count_states_and_arcs (automaton, &states_num, &arcs_num);
6310 automaton->minimal_DFA_states_num = states_num;
6311 automaton->minimal_DFA_arcs_num = arcs_num;
6317 /* The page contains code for enumeration of all states of an automaton. */
6319 /* Variable used for enumeration of all states of an automaton. Its
6320 value is current number of automaton states. */
6321 static int curr_state_order_num;
6323 /* The function is called by function `pass_states' for enumerating
6324 states. */
6325 static void
6326 set_order_state_num (state_t state)
6328 state->order_state_num = curr_state_order_num;
6329 curr_state_order_num++;
6332 /* The function enumerates all states of AUTOMATON. */
6333 static void
6334 enumerate_states (automaton_t automaton)
6336 curr_state_order_num = 0;
6337 pass_states (automaton, set_order_state_num);
6338 automaton->achieved_states_num = curr_state_order_num;
6343 /* The page contains code for finding equivalent automaton insns
6344 (ainsns). */
6346 /* The function inserts AINSN into cyclic list
6347 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6348 static ainsn_t
6349 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6350 ainsn_t cyclic_equiv_class_insn_list)
6352 if (cyclic_equiv_class_insn_list == NULL)
6353 ainsn->next_equiv_class_insn = ainsn;
6354 else
6356 ainsn->next_equiv_class_insn
6357 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6358 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6360 return ainsn;
6363 /* The function deletes equiv_class_insn into cyclic list of
6364 equivalent ainsns. */
6365 static void
6366 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6368 ainsn_t curr_equiv_class_insn;
6369 ainsn_t prev_equiv_class_insn;
6371 prev_equiv_class_insn = equiv_class_insn;
6372 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6373 curr_equiv_class_insn != equiv_class_insn;
6374 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6375 prev_equiv_class_insn = curr_equiv_class_insn;
6376 if (prev_equiv_class_insn != equiv_class_insn)
6377 prev_equiv_class_insn->next_equiv_class_insn
6378 = equiv_class_insn->next_equiv_class_insn;
6381 /* The function processes AINSN of a state in order to find equivalent
6382 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6383 state. */
6384 static void
6385 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6387 ainsn_t next_insn;
6388 ainsn_t curr_insn;
6389 ainsn_t cyclic_insn_list;
6390 arc_t arc;
6392 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6393 curr_insn = ainsn;
6394 /* New class of ainsns which are not equivalent to given ainsn. */
6395 cyclic_insn_list = NULL;
6398 next_insn = curr_insn->next_equiv_class_insn;
6399 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6400 if (arc == NULL
6401 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6402 != arc->to_state))
6404 delete_ainsn_from_equiv_class (curr_insn);
6405 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6406 cyclic_insn_list);
6408 curr_insn = next_insn;
6410 while (curr_insn != ainsn);
6413 /* The function processes STATE in order to find equivalent ainsns. */
6414 static void
6415 process_state_for_insn_equiv_partition (state_t state)
6417 arc_t arc;
6418 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6420 /* Process insns of the arcs. */
6421 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6422 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6423 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6424 process_insn_equiv_class (arc->insn, insn_arcs_array);
6426 free (insn_arcs_array);
6429 /* The function searches for equivalent ainsns of AUTOMATON. */
6430 static void
6431 set_insn_equiv_classes (automaton_t automaton)
6433 ainsn_t ainsn;
6434 ainsn_t first_insn;
6435 ainsn_t curr_insn;
6436 ainsn_t cyclic_insn_list;
6437 ainsn_t insn_with_same_reservs;
6438 int equiv_classes_num;
6440 /* All insns are included in one equivalence class. */
6441 cyclic_insn_list = NULL;
6442 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6443 if (ainsn->first_insn_with_same_reservs)
6444 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6445 cyclic_insn_list);
6446 /* Process insns in order to make equivalence partition. */
6447 pass_states (automaton, process_state_for_insn_equiv_partition);
6448 /* Enumerate equiv classes. */
6449 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6450 /* Set undefined value. */
6451 ainsn->insn_equiv_class_num = -1;
6452 equiv_classes_num = 0;
6453 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6454 if (ainsn->insn_equiv_class_num < 0)
6456 first_insn = ainsn;
6457 gcc_assert (first_insn->first_insn_with_same_reservs);
6458 first_insn->first_ainsn_with_given_equivalence_num = 1;
6459 curr_insn = first_insn;
6462 for (insn_with_same_reservs = curr_insn;
6463 insn_with_same_reservs != NULL;
6464 insn_with_same_reservs
6465 = insn_with_same_reservs->next_same_reservs_insn)
6466 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6467 curr_insn = curr_insn->next_equiv_class_insn;
6469 while (curr_insn != first_insn);
6470 equiv_classes_num++;
6472 automaton->insn_equiv_classes_num = equiv_classes_num;
6477 /* This page contains code for creating DFA(s) and calls functions
6478 building them. */
6481 /* The following value is used to prevent floating point overflow for
6482 estimating an automaton bound. The value should be less DBL_MAX on
6483 the host machine. We use here approximate minimum of maximal
6484 double floating point value required by ANSI C standard. It
6485 will work for non ANSI sun compiler too. */
6487 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6489 /* The function estimate size of the single DFA used by PHR (pipeline
6490 hazards recognizer). */
6491 static double
6492 estimate_one_automaton_bound (void)
6494 decl_t decl;
6495 double one_automaton_estimation_bound;
6496 double root_value;
6497 int i;
6499 one_automaton_estimation_bound = 1.0;
6500 for (i = 0; i < description->decls_num; i++)
6502 decl = description->decls [i];
6503 if (decl->mode == dm_unit)
6505 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6506 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6507 / automata_num);
6508 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6509 > one_automaton_estimation_bound)
6510 one_automaton_estimation_bound *= root_value;
6513 return one_automaton_estimation_bound;
6516 /* The function compares unit declarations according to their maximal
6517 cycle in reservations. */
6518 static int
6519 compare_max_occ_cycle_nums (const void *unit_decl_1,
6520 const void *unit_decl_2)
6522 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6523 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6524 return 1;
6525 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6526 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6527 return 0;
6528 else
6529 return -1;
6532 /* The function makes heuristic assigning automata to units. Actually
6533 efficacy of the algorithm has been checked yet??? */
6535 static void
6536 units_to_automata_heuristic_distr (void)
6538 double estimation_bound;
6539 int automaton_num;
6540 int rest_units_num;
6541 double bound_value;
6542 unit_decl_t *unit_decls;
6543 int i, j;
6545 if (description->units_num == 0)
6546 return;
6547 estimation_bound = estimate_one_automaton_bound ();
6548 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6550 for (i = 0, j = 0; i < description->decls_num; i++)
6551 if (description->decls[i]->mode == dm_unit)
6552 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6553 gcc_assert (j == description->units_num);
6555 qsort (unit_decls, description->units_num,
6556 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6558 automaton_num = 0;
6559 bound_value = unit_decls[0]->max_occ_cycle_num;
6560 unit_decls[0]->corresponding_automaton_num = automaton_num;
6562 for (i = 1; i < description->units_num; i++)
6564 rest_units_num = description->units_num - i + 1;
6565 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6566 if (automaton_num < automata_num - 1
6567 && ((automata_num - automaton_num - 1 == rest_units_num)
6568 || (bound_value
6569 > (estimation_bound
6570 / unit_decls[i]->max_occ_cycle_num))))
6572 bound_value = unit_decls[i]->max_occ_cycle_num;
6573 automaton_num++;
6575 else
6576 bound_value *= unit_decls[i]->max_occ_cycle_num;
6577 unit_decls[i]->corresponding_automaton_num = automaton_num;
6579 gcc_assert (automaton_num == automata_num - 1);
6580 free (unit_decls);
6583 /* The functions creates automaton insns for each automata. Automaton
6584 insn is simply insn for given automaton which makes reservation
6585 only of units of the automaton. */
6586 static ainsn_t
6587 create_ainsns (void)
6589 decl_t decl;
6590 ainsn_t first_ainsn;
6591 ainsn_t curr_ainsn;
6592 ainsn_t prev_ainsn;
6593 int i;
6595 first_ainsn = NULL;
6596 prev_ainsn = NULL;
6597 for (i = 0; i < description->decls_num; i++)
6599 decl = description->decls [i];
6600 if (decl->mode == dm_insn_reserv)
6602 curr_ainsn = XCREATENODE (struct ainsn);
6603 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6604 curr_ainsn->important_p = FALSE;
6605 curr_ainsn->next_ainsn = NULL;
6606 if (prev_ainsn == NULL)
6607 first_ainsn = curr_ainsn;
6608 else
6609 prev_ainsn->next_ainsn = curr_ainsn;
6610 prev_ainsn = curr_ainsn;
6613 return first_ainsn;
6616 /* The function assigns automata to units according to constructions
6617 `define_automaton' in the description. */
6618 static void
6619 units_to_automata_distr (void)
6621 decl_t decl;
6622 int i;
6624 for (i = 0; i < description->decls_num; i++)
6626 decl = description->decls [i];
6627 if (decl->mode == dm_unit)
6629 if (DECL_UNIT (decl)->automaton_decl == NULL
6630 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6631 == NULL))
6632 /* Distribute to the first automaton. */
6633 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6634 else
6635 DECL_UNIT (decl)->corresponding_automaton_num
6636 = (DECL_UNIT (decl)->automaton_decl
6637 ->corresponding_automaton->automaton_order_num);
6642 /* The function creates DFA(s) for fast pipeline hazards recognition
6643 after checking and simplifying IR of the description. */
6644 static void
6645 create_automata (void)
6647 automaton_t curr_automaton;
6648 automaton_t prev_automaton;
6649 decl_t decl;
6650 int curr_automaton_num;
6651 int i;
6653 if (automata_num != 0)
6655 units_to_automata_heuristic_distr ();
6656 for (prev_automaton = NULL, curr_automaton_num = 0;
6657 curr_automaton_num < automata_num;
6658 curr_automaton_num++, prev_automaton = curr_automaton)
6660 curr_automaton = XCREATENODE (struct automaton);
6661 curr_automaton->ainsn_list = create_ainsns ();
6662 curr_automaton->corresponding_automaton_decl = NULL;
6663 curr_automaton->next_automaton = NULL;
6664 curr_automaton->automaton_order_num = curr_automaton_num;
6665 if (prev_automaton == NULL)
6666 description->first_automaton = curr_automaton;
6667 else
6668 prev_automaton->next_automaton = curr_automaton;
6671 else
6673 curr_automaton_num = 0;
6674 prev_automaton = NULL;
6675 for (i = 0; i < description->decls_num; i++)
6677 decl = description->decls [i];
6678 if (decl->mode == dm_automaton
6679 && DECL_AUTOMATON (decl)->automaton_is_used)
6681 curr_automaton = XCREATENODE (struct automaton);
6682 curr_automaton->ainsn_list = create_ainsns ();
6683 curr_automaton->corresponding_automaton_decl
6684 = DECL_AUTOMATON (decl);
6685 curr_automaton->next_automaton = NULL;
6686 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6687 curr_automaton->automaton_order_num = curr_automaton_num;
6688 if (prev_automaton == NULL)
6689 description->first_automaton = curr_automaton;
6690 else
6691 prev_automaton->next_automaton = curr_automaton;
6692 curr_automaton_num++;
6693 prev_automaton = curr_automaton;
6696 if (curr_automaton_num == 0)
6698 curr_automaton = XCREATENODE (struct automaton);
6699 curr_automaton->ainsn_list = create_ainsns ();
6700 curr_automaton->corresponding_automaton_decl = NULL;
6701 curr_automaton->next_automaton = NULL;
6702 description->first_automaton = curr_automaton;
6704 units_to_automata_distr ();
6706 NDFA_time = create_ticker ();
6707 ticker_off (&NDFA_time);
6708 NDFA_to_DFA_time = create_ticker ();
6709 ticker_off (&NDFA_to_DFA_time);
6710 minimize_time = create_ticker ();
6711 ticker_off (&minimize_time);
6712 equiv_time = create_ticker ();
6713 ticker_off (&equiv_time);
6714 for (curr_automaton = description->first_automaton;
6715 curr_automaton != NULL;
6716 curr_automaton = curr_automaton->next_automaton)
6718 if (progress_flag)
6720 if (curr_automaton->corresponding_automaton_decl == NULL)
6721 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6722 else
6723 fprintf (stderr, "Prepare automaton `%s' creation...",
6724 curr_automaton->corresponding_automaton_decl->name);
6726 create_alt_states (curr_automaton);
6727 form_ainsn_with_same_reservs (curr_automaton);
6728 if (progress_flag)
6729 fprintf (stderr, "done\n");
6730 build_automaton (curr_automaton);
6731 enumerate_states (curr_automaton);
6732 ticker_on (&equiv_time);
6733 set_insn_equiv_classes (curr_automaton);
6734 ticker_off (&equiv_time);
6740 /* This page contains code for forming string representation of
6741 regexp. The representation is formed on IR obstack. So you should
6742 not work with IR obstack between regexp_representation and
6743 finish_regexp_representation calls. */
6745 /* This recursive function forms string representation of regexp
6746 (without tailing '\0'). */
6747 static void
6748 form_regexp (regexp_t regexp)
6750 int i;
6752 switch (regexp->mode)
6754 case rm_unit: case rm_reserv:
6756 const char *name = (regexp->mode == rm_unit
6757 ? REGEXP_UNIT (regexp)->name
6758 : REGEXP_RESERV (regexp)->name);
6760 obstack_grow (&irp, name, strlen (name));
6761 break;
6764 case rm_sequence:
6765 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6767 if (i != 0)
6768 obstack_1grow (&irp, ',');
6769 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6771 break;
6773 case rm_allof:
6774 obstack_1grow (&irp, '(');
6775 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6777 if (i != 0)
6778 obstack_1grow (&irp, '+');
6779 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6780 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6781 obstack_1grow (&irp, '(');
6782 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6783 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6784 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6785 obstack_1grow (&irp, ')');
6787 obstack_1grow (&irp, ')');
6788 break;
6790 case rm_oneof:
6791 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6793 if (i != 0)
6794 obstack_1grow (&irp, '|');
6795 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6796 obstack_1grow (&irp, '(');
6797 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6798 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6799 obstack_1grow (&irp, ')');
6801 break;
6803 case rm_repeat:
6805 char digits [30];
6807 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6808 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6809 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6810 obstack_1grow (&irp, '(');
6811 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6812 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6813 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6814 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6815 obstack_1grow (&irp, ')');
6816 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6817 obstack_grow (&irp, digits, strlen (digits));
6818 break;
6821 case rm_nothing:
6822 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6823 break;
6825 default:
6826 gcc_unreachable ();
6830 /* The function returns string representation of REGEXP on IR
6831 obstack. */
6832 static const char *
6833 regexp_representation (regexp_t regexp)
6835 form_regexp (regexp);
6836 obstack_1grow (&irp, '\0');
6837 return obstack_base (&irp);
6840 /* The function frees memory allocated for last formed string
6841 representation of regexp. */
6842 static void
6843 finish_regexp_representation (void)
6845 int length = obstack_object_size (&irp);
6847 obstack_blank_fast (&irp, -length);
6852 /* This page contains code for output PHR (pipeline hazards recognizer). */
6854 /* The function outputs minimal C type which is sufficient for
6855 representation numbers in range min_range_value and
6856 max_range_value. Because host machine and build machine may be
6857 different, we use here minimal values required by ANSI C standard
6858 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6859 approximation. */
6861 static void
6862 output_range_type (FILE *f, long int min_range_value,
6863 long int max_range_value)
6865 if (min_range_value >= 0 && max_range_value <= 255)
6866 fprintf (f, "unsigned char");
6867 else if (min_range_value >= -127 && max_range_value <= 127)
6868 fprintf (f, "signed char");
6869 else if (min_range_value >= 0 && max_range_value <= 65535)
6870 fprintf (f, "unsigned short");
6871 else if (min_range_value >= -32767 && max_range_value <= 32767)
6872 fprintf (f, "short");
6873 else
6874 fprintf (f, "int");
6877 /* The function outputs all initialization values of VECT. */
6878 static void
6879 output_vect (vla_hwint_t vect)
6881 int els_on_line;
6882 size_t vect_length = VEC_length (vect_el_t, vect);
6883 size_t i;
6885 els_on_line = 1;
6886 if (vect_length == 0)
6887 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6888 else
6889 for (i = 0; i < vect_length; i++)
6891 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6892 if (els_on_line == 10)
6894 els_on_line = 0;
6895 fputs (",\n", output_file);
6897 else if (i < vect_length-1)
6898 fputs (", ", output_file);
6899 els_on_line++;
6903 /* The following is name of the structure which represents DFA(s) for
6904 PHR. */
6905 #define CHIP_NAME "DFA_chip"
6907 /* The following is name of member which represents state of a DFA for
6908 PHR. */
6909 static void
6910 output_chip_member_name (FILE *f, automaton_t automaton)
6912 if (automaton->corresponding_automaton_decl == NULL)
6913 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6914 else
6915 fprintf (f, "%s_automaton_state",
6916 automaton->corresponding_automaton_decl->name);
6919 /* The following is name of temporary variable which stores state of a
6920 DFA for PHR. */
6921 static void
6922 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6924 fprintf (f, "_");
6925 output_chip_member_name (f, automaton);
6928 /* This is name of macro value which is code of pseudo_insn
6929 representing advancing cpu cycle. Its value is used as internal
6930 code unknown insn. */
6931 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6933 /* Output name of translate vector for given automaton. */
6934 static void
6935 output_translate_vect_name (FILE *f, automaton_t automaton)
6937 if (automaton->corresponding_automaton_decl == NULL)
6938 fprintf (f, "translate_%d", automaton->automaton_order_num);
6939 else
6940 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6943 /* Output name for simple transition table representation. */
6944 static void
6945 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6947 if (automaton->corresponding_automaton_decl == NULL)
6948 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6949 else
6950 fprintf (f, "%s_transitions",
6951 automaton->corresponding_automaton_decl->name);
6954 /* Output name of comb vector of the transition table for given
6955 automaton. */
6956 static void
6957 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6959 if (automaton->corresponding_automaton_decl == NULL)
6960 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6961 else
6962 fprintf (f, "%s_transitions",
6963 automaton->corresponding_automaton_decl->name);
6966 /* Output name of check vector of the transition table for given
6967 automaton. */
6968 static void
6969 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6971 if (automaton->corresponding_automaton_decl == NULL)
6972 fprintf (f, "check_%d", automaton->automaton_order_num);
6973 else
6974 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6977 /* Output name of base vector of the transition table for given
6978 automaton. */
6979 static void
6980 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6982 if (automaton->corresponding_automaton_decl == NULL)
6983 fprintf (f, "base_%d", automaton->automaton_order_num);
6984 else
6985 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6988 /* Output name of simple min issue delay table representation. */
6989 static void
6990 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6992 if (automaton->corresponding_automaton_decl == NULL)
6993 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6994 else
6995 fprintf (f, "%s_min_issue_delay",
6996 automaton->corresponding_automaton_decl->name);
6999 /* Output name of deadlock vector for given automaton. */
7000 static void
7001 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7003 if (automaton->corresponding_automaton_decl == NULL)
7004 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7005 else
7006 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7009 /* Output name of reserved units table for AUTOMATON into file F. */
7010 static void
7011 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7013 if (automaton->corresponding_automaton_decl == NULL)
7014 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7015 else
7016 fprintf (f, "%s_reserved_units",
7017 automaton->corresponding_automaton_decl->name);
7020 /* Name of the PHR interface macro. */
7021 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7023 /* Names of an internal functions: */
7024 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7026 /* This is external type of DFA(s) state. */
7027 #define STATE_TYPE_NAME "state_t"
7029 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7031 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7033 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7035 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7037 /* Name of cache of insn dfa codes. */
7038 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7040 /* Name of length of cache of insn dfa codes. */
7041 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7043 /* Names of the PHR interface functions: */
7044 #define SIZE_FUNC_NAME "state_size"
7046 #define TRANSITION_FUNC_NAME "state_transition"
7048 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7050 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7052 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7054 #define RESET_FUNC_NAME "state_reset"
7056 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7058 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7060 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7062 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7064 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7066 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7068 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7070 #define DFA_START_FUNC_NAME "dfa_start"
7072 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7074 /* Names of parameters of the PHR interface functions. */
7075 #define STATE_NAME "state"
7077 #define INSN_PARAMETER_NAME "insn"
7079 #define INSN2_PARAMETER_NAME "insn2"
7081 #define CHIP_PARAMETER_NAME "chip"
7083 #define FILE_PARAMETER_NAME "f"
7085 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7087 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7089 /* Names of the variables whose values are internal insn code of rtx
7090 insn. */
7091 #define INTERNAL_INSN_CODE_NAME "insn_code"
7093 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7095 /* Names of temporary variables in some functions. */
7096 #define TEMPORARY_VARIABLE_NAME "temp"
7098 #define I_VARIABLE_NAME "i"
7100 /* Name of result variable in some functions. */
7101 #define RESULT_VARIABLE_NAME "res"
7103 /* Name of function (attribute) to translate insn into internal insn
7104 code. */
7105 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7107 /* Name of function (attribute) to translate insn into internal insn
7108 code with caching. */
7109 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7111 /* Output C type which is used for representation of codes of states
7112 of AUTOMATON. */
7113 static void
7114 output_state_member_type (FILE *f, automaton_t automaton)
7116 output_range_type (f, 0, automaton->achieved_states_num);
7119 /* Output definition of the structure representing current DFA(s)
7120 state(s). */
7121 static void
7122 output_chip_definitions (void)
7124 automaton_t automaton;
7126 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7127 for (automaton = description->first_automaton;
7128 automaton != NULL;
7129 automaton = automaton->next_automaton)
7131 fprintf (output_file, " ");
7132 output_state_member_type (output_file, automaton);
7133 fprintf (output_file, " ");
7134 output_chip_member_name (output_file, automaton);
7135 fprintf (output_file, ";\n");
7137 fprintf (output_file, "};\n\n");
7138 #if 0
7139 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7140 #endif
7144 /* The function outputs translate vector of internal insn code into
7145 insn equivalence class number. The equivalence class number is
7146 used to access to table and vectors representing DFA(s). */
7147 static void
7148 output_translate_vect (automaton_t automaton)
7150 ainsn_t ainsn;
7151 int insn_value;
7152 vla_hwint_t translate_vect;
7154 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7156 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7157 /* Undefined value */
7158 VEC_quick_push (vect_el_t, translate_vect,
7159 automaton->insn_equiv_classes_num);
7161 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7162 VEC_replace (vect_el_t, translate_vect,
7163 ainsn->insn_reserv_decl->insn_num,
7164 ainsn->insn_equiv_class_num);
7166 fprintf (output_file,
7167 "/* Vector translating external insn codes to internal ones.*/\n");
7168 fprintf (output_file, "static const ");
7169 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7170 fprintf (output_file, " ");
7171 output_translate_vect_name (output_file, automaton);
7172 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7173 output_vect (translate_vect);
7174 fprintf (output_file, "};\n\n");
7175 VEC_free (vect_el_t, heap, translate_vect);
7178 /* The value in a table state x ainsn -> something which represents
7179 undefined value. */
7180 static int undefined_vect_el_value;
7182 /* The following function returns nonzero value if the best
7183 representation of the table is comb vector. */
7184 static int
7185 comb_vect_p (state_ainsn_table_t tab)
7187 return (2 * VEC_length (vect_el_t, tab->full_vect)
7188 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7191 /* The following function creates new table for AUTOMATON. */
7192 static state_ainsn_table_t
7193 create_state_ainsn_table (automaton_t automaton)
7195 state_ainsn_table_t tab;
7196 int full_vect_length;
7197 int i;
7199 tab = XCREATENODE (struct state_ainsn_table);
7200 tab->automaton = automaton;
7202 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7203 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7205 tab->base_vect = 0;
7206 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7207 automaton->achieved_states_num);
7209 full_vect_length = (automaton->insn_equiv_classes_num
7210 * automaton->achieved_states_num);
7211 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7212 for (i = 0; i < full_vect_length; i++)
7213 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7215 tab->min_base_vect_el_value = 0;
7216 tab->max_base_vect_el_value = 0;
7217 tab->min_comb_vect_el_value = 0;
7218 tab->max_comb_vect_el_value = 0;
7219 return tab;
7222 /* The following function outputs the best C representation of the
7223 table TAB of given TABLE_NAME. */
7224 static void
7225 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7226 void (*output_full_vect_name_func) (FILE *, automaton_t),
7227 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7228 void (*output_check_vect_name_func) (FILE *, automaton_t),
7229 void (*output_base_vect_name_func) (FILE *, automaton_t))
7231 if (!comb_vect_p (tab))
7233 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7234 fprintf (output_file, "static const ");
7235 output_range_type (output_file, tab->min_comb_vect_el_value,
7236 tab->max_comb_vect_el_value);
7237 fprintf (output_file, " ");
7238 (*output_full_vect_name_func) (output_file, tab->automaton);
7239 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7240 output_vect (tab->full_vect);
7241 fprintf (output_file, "};\n\n");
7243 else
7245 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7246 fprintf (output_file, "static const ");
7247 output_range_type (output_file, tab->min_comb_vect_el_value,
7248 tab->max_comb_vect_el_value);
7249 fprintf (output_file, " ");
7250 (*output_comb_vect_name_func) (output_file, tab->automaton);
7251 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7252 output_vect (tab->comb_vect);
7253 fprintf (output_file, "};\n\n");
7254 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7255 fprintf (output_file, "static const ");
7256 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7257 fprintf (output_file, " ");
7258 (*output_check_vect_name_func) (output_file, tab->automaton);
7259 fprintf (output_file, "[] = {\n");
7260 output_vect (tab->check_vect);
7261 fprintf (output_file, "};\n\n");
7262 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7263 fprintf (output_file, "static const ");
7264 output_range_type (output_file, tab->min_base_vect_el_value,
7265 tab->max_base_vect_el_value);
7266 fprintf (output_file, " ");
7267 (*output_base_vect_name_func) (output_file, tab->automaton);
7268 fprintf (output_file, "[] = {\n");
7269 output_vect (tab->base_vect);
7270 fprintf (output_file, "};\n\n");
7274 /* The following function adds vector VECT to table TAB as its line
7275 with number VECT_NUM. */
7276 static void
7277 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7279 int vect_length;
7280 size_t real_vect_length;
7281 int comb_vect_index;
7282 int comb_vect_els_num;
7283 int vect_index;
7284 int first_unempty_vect_index;
7285 int additional_els_num;
7286 int no_state_value;
7287 vect_el_t vect_el;
7288 int i;
7289 unsigned long vect_mask, comb_vect_mask;
7291 vect_length = VEC_length (vect_el_t, vect);
7292 gcc_assert (vect_length);
7293 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7294 real_vect_length = tab->automaton->insn_equiv_classes_num;
7295 /* Form full vector in the table: */
7297 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7298 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7299 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7300 full_base + vect_length);
7301 for (i = 0; i < vect_length; i++)
7302 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7303 VEC_index (vect_el_t, vect, i));
7305 /* Form comb vector in the table: */
7306 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7307 == VEC_length (vect_el_t, tab->check_vect));
7309 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7310 for (first_unempty_vect_index = 0;
7311 first_unempty_vect_index < vect_length;
7312 first_unempty_vect_index++)
7313 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7314 != undefined_vect_el_value)
7315 break;
7317 /* Search for the place in comb vect for the inserted vect. */
7319 /* Slow case. */
7320 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7322 for (comb_vect_index = 0;
7323 comb_vect_index < comb_vect_els_num;
7324 comb_vect_index++)
7326 for (vect_index = first_unempty_vect_index;
7327 vect_index < vect_length
7328 && vect_index + comb_vect_index < comb_vect_els_num;
7329 vect_index++)
7330 if (VEC_index (vect_el_t, vect, vect_index)
7331 != undefined_vect_el_value
7332 && (VEC_index (vect_el_t, tab->comb_vect,
7333 vect_index + comb_vect_index)
7334 != undefined_vect_el_value))
7335 break;
7336 if (vect_index >= vect_length
7337 || vect_index + comb_vect_index >= comb_vect_els_num)
7338 break;
7340 goto found;
7343 /* Fast case. */
7344 vect_mask = 0;
7345 for (vect_index = first_unempty_vect_index;
7346 vect_index < vect_length;
7347 vect_index++)
7349 vect_mask = vect_mask << 1;
7350 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7351 vect_mask |= 1;
7354 /* Search for the place in comb vect for the inserted vect. */
7355 comb_vect_index = 0;
7356 if (comb_vect_els_num == 0)
7357 goto found;
7359 comb_vect_mask = 0;
7360 for (vect_index = first_unempty_vect_index;
7361 vect_index < vect_length && vect_index < comb_vect_els_num;
7362 vect_index++)
7364 comb_vect_mask <<= 1;
7365 if (vect_index + comb_vect_index < comb_vect_els_num
7366 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7367 != undefined_vect_el_value)
7368 comb_vect_mask |= 1;
7370 if ((vect_mask & comb_vect_mask) == 0)
7371 goto found;
7373 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7374 comb_vect_index++, i++)
7376 comb_vect_mask = (comb_vect_mask << 1) | 1;
7377 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7378 == undefined_vect_el_value);
7379 if ((vect_mask & comb_vect_mask) == 0)
7380 goto found;
7382 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7384 comb_vect_mask <<= 1;
7385 if ((vect_mask & comb_vect_mask) == 0)
7386 goto found;
7389 found:
7390 /* Slot was found. */
7391 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7392 if (additional_els_num < 0)
7393 additional_els_num = 0;
7394 /* Expand comb and check vectors. */
7395 vect_el = undefined_vect_el_value;
7396 no_state_value = tab->automaton->achieved_states_num;
7397 while (additional_els_num > 0)
7399 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7400 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7401 additional_els_num--;
7403 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7404 >= comb_vect_index + real_vect_length);
7405 /* Fill comb and check vectors. */
7406 for (vect_index = 0; vect_index < vect_length; vect_index++)
7407 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7409 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7410 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7411 comb_vect_index + vect_index)
7412 == undefined_vect_el_value);
7413 gcc_assert (x >= 0);
7414 if (tab->max_comb_vect_el_value < x)
7415 tab->max_comb_vect_el_value = x;
7416 if (tab->min_comb_vect_el_value > x)
7417 tab->min_comb_vect_el_value = x;
7418 VEC_replace (vect_el_t, tab->comb_vect,
7419 comb_vect_index + vect_index, x);
7420 VEC_replace (vect_el_t, tab->check_vect,
7421 comb_vect_index + vect_index, vect_num);
7423 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7424 tab->max_comb_vect_el_value = undefined_vect_el_value;
7425 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7426 tab->min_comb_vect_el_value = undefined_vect_el_value;
7427 if (tab->max_base_vect_el_value < comb_vect_index)
7428 tab->max_base_vect_el_value = comb_vect_index;
7429 if (tab->min_base_vect_el_value > comb_vect_index)
7430 tab->min_base_vect_el_value = comb_vect_index;
7432 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7435 /* Return number of out arcs of STATE. */
7436 static int
7437 out_state_arcs_num (const_state_t state)
7439 int result;
7440 arc_t arc;
7442 result = 0;
7443 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7445 gcc_assert (arc->insn);
7446 if (arc->insn->first_ainsn_with_given_equivalence_num)
7447 result++;
7449 return result;
7452 /* Compare number of possible transitions from the states. */
7453 static int
7454 compare_transition_els_num (const void *state_ptr_1,
7455 const void *state_ptr_2)
7457 const int transition_els_num_1
7458 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7459 const int transition_els_num_2
7460 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7462 if (transition_els_num_1 < transition_els_num_2)
7463 return 1;
7464 else if (transition_els_num_1 == transition_els_num_2)
7465 return 0;
7466 else
7467 return -1;
7470 /* The function adds element EL_VALUE to vector VECT for a table state
7471 x AINSN. */
7472 static void
7473 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7475 int equiv_class_num;
7476 int vect_index;
7478 gcc_assert (ainsn);
7479 equiv_class_num = ainsn->insn_equiv_class_num;
7480 for (vect_index = VEC_length (vect_el_t, *vect);
7481 vect_index <= equiv_class_num;
7482 vect_index++)
7483 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7484 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7487 /* This is for forming vector of states of an automaton. */
7488 static VEC(state_t, heap) *output_states_vect;
7490 /* The function is called by function pass_states. The function adds
7491 STATE to `output_states_vect'. */
7492 static void
7493 add_states_vect_el (state_t state)
7495 VEC_safe_push (state_t, heap, output_states_vect, state);
7498 /* Form and output vectors (comb, check, base or full vector)
7499 representing transition table of AUTOMATON. */
7500 static void
7501 output_trans_table (automaton_t automaton)
7503 size_t i;
7504 arc_t arc;
7505 vla_hwint_t transition_vect = 0;
7507 undefined_vect_el_value = automaton->achieved_states_num;
7508 automaton->trans_table = create_state_ainsn_table (automaton);
7509 /* Create vect of pointers to states ordered by num of transitions
7510 from the state (state with the maximum num is the first). */
7511 output_states_vect = 0;
7512 pass_states (automaton, add_states_vect_el);
7513 VEC_qsort (state_t, output_states_vect, compare_transition_els_num);
7515 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7517 VEC_truncate (vect_el_t, transition_vect, 0);
7518 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7519 arc != NULL;
7520 arc = next_out_arc (arc))
7522 gcc_assert (arc->insn);
7523 if (arc->insn->first_ainsn_with_given_equivalence_num)
7524 add_vect_el (&transition_vect, arc->insn,
7525 arc->to_state->order_state_num);
7527 add_vect (automaton->trans_table,
7528 VEC_index (state_t, output_states_vect, i)->order_state_num,
7529 transition_vect);
7531 output_state_ainsn_table
7532 (automaton->trans_table, "state transitions",
7533 output_trans_full_vect_name, output_trans_comb_vect_name,
7534 output_trans_check_vect_name, output_trans_base_vect_name);
7536 VEC_free (state_t, heap, output_states_vect);
7537 VEC_free (vect_el_t, heap, transition_vect);
7540 /* Form and output vectors representing minimal issue delay table of
7541 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7542 the ainsn. */
7543 static void
7544 output_min_issue_delay_table (automaton_t automaton)
7546 vla_hwint_t min_issue_delay_vect;
7547 vla_hwint_t compressed_min_issue_delay_vect;
7548 ainsn_t ainsn;
7549 size_t i;
7550 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7551 size_t cfactor;
7552 int changed;
7554 /* Create vect of pointers to states ordered by num of transitions
7555 from the state (state with the maximum num is the first). */
7556 output_states_vect = 0;
7557 pass_states (automaton, add_states_vect_el);
7559 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7560 * automaton->insn_equiv_classes_num);
7561 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7562 for (i = 0; i < min_issue_delay_len; i++)
7563 VEC_quick_push (vect_el_t, min_issue_delay_vect, -1);
7565 automaton->max_min_delay = 0;
7569 size_t state_no;
7571 changed = 0;
7573 for (state_no = 0; state_no < VEC_length (state_t, output_states_vect);
7574 state_no++)
7576 state_t s = VEC_index (state_t, output_states_vect, state_no);
7577 arc_t arc;
7579 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7581 int k;
7583 size_t asn = s->order_state_num
7584 * automaton->insn_equiv_classes_num
7585 + arc->insn->insn_equiv_class_num;
7587 if (VEC_index (vect_el_t, min_issue_delay_vect, asn))
7589 VEC_replace (vect_el_t, min_issue_delay_vect, asn, 0);
7590 changed = 1;
7593 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7595 size_t n0, n1;
7596 vect_el_t delay0, delay1;
7598 n0 = s->order_state_num
7599 * automaton->insn_equiv_classes_num
7600 + k;
7601 n1 = arc->to_state->order_state_num
7602 * automaton->insn_equiv_classes_num
7603 + k;
7604 delay0 = VEC_index (vect_el_t, min_issue_delay_vect, n0);
7605 delay1 = VEC_index (vect_el_t, min_issue_delay_vect, n1);
7606 if (delay1 != -1)
7608 if (arc->insn->insn_reserv_decl
7609 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7610 delay1++;
7611 if (delay1 < delay0 || delay0 == -1)
7613 VEC_replace (vect_el_t, min_issue_delay_vect, n0, delay1);
7614 changed = 1;
7621 while (changed);
7623 automaton->max_min_delay = 0;
7625 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7626 if (ainsn->first_ainsn_with_given_equivalence_num)
7628 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7630 state_t s = VEC_index (state_t, output_states_vect, i);
7631 size_t np = s->order_state_num
7632 * automaton->insn_equiv_classes_num
7633 + ainsn->insn_equiv_class_num;
7634 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, np);
7636 if (automaton->max_min_delay < x)
7637 automaton->max_min_delay = x;
7638 if (x == -1)
7639 VEC_replace (vect_el_t, min_issue_delay_vect, np, 0);
7643 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7644 fprintf (output_file, "static const ");
7645 output_range_type (output_file, 0, automaton->max_min_delay);
7646 fprintf (output_file, " ");
7647 output_min_issue_delay_vect_name (output_file, automaton);
7648 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7649 /* Compress the vector. */
7650 if (automaton->max_min_delay < 2)
7651 cfactor = 8;
7652 else if (automaton->max_min_delay < 4)
7653 cfactor = 4;
7654 else if (automaton->max_min_delay < 16)
7655 cfactor = 2;
7656 else
7657 cfactor = 1;
7658 automaton->min_issue_delay_table_compression_factor = cfactor;
7660 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7661 compressed_min_issue_delay_vect
7662 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7664 for (i = 0; i < compressed_min_issue_delay_len; i++)
7665 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7667 for (i = 0; i < min_issue_delay_len; i++)
7669 size_t ci = i / cfactor;
7670 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7671 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7673 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7674 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7676 output_vect (compressed_min_issue_delay_vect);
7677 fprintf (output_file, "};\n\n");
7678 VEC_free (state_t, heap, output_states_vect);
7679 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7680 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7683 /* Form and output vector representing the locked states of
7684 AUTOMATON. */
7685 static void
7686 output_dead_lock_vect (automaton_t automaton)
7688 size_t i;
7689 arc_t arc;
7690 vla_hwint_t dead_lock_vect = 0;
7692 /* Create vect of pointers to states ordered by num of
7693 transitions from the state (state with the maximum num is the
7694 first). */
7695 automaton->locked_states = 0;
7696 output_states_vect = 0;
7697 pass_states (automaton, add_states_vect_el);
7699 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7700 VEC_length (state_t, output_states_vect));
7701 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7703 state_t s = VEC_index (state_t, output_states_vect, i);
7704 arc = first_out_arc (s);
7705 gcc_assert (arc);
7706 if (next_out_arc (arc) == NULL
7707 && (arc->insn->insn_reserv_decl
7708 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7710 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7711 automaton->locked_states++;
7713 else
7714 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7716 if (automaton->locked_states == 0)
7717 return;
7719 fprintf (output_file, "/* Vector for locked state flags. */\n");
7720 fprintf (output_file, "static const ");
7721 output_range_type (output_file, 0, 1);
7722 fprintf (output_file, " ");
7723 output_dead_lock_vect_name (output_file, automaton);
7724 fprintf (output_file, "[] = {\n");
7725 output_vect (dead_lock_vect);
7726 fprintf (output_file, "};\n\n");
7727 VEC_free (state_t, heap, output_states_vect);
7728 VEC_free (vect_el_t, heap, dead_lock_vect);
7731 /* Form and output vector representing reserved units of the states of
7732 AUTOMATON. */
7733 static void
7734 output_reserved_units_table (automaton_t automaton)
7736 vla_hwint_t reserved_units_table = 0;
7737 int state_byte_size;
7738 int reserved_units_size;
7739 size_t n;
7740 int i;
7742 if (description->query_units_num == 0)
7743 return;
7745 /* Create vect of pointers to states. */
7746 output_states_vect = 0;
7747 pass_states (automaton, add_states_vect_el);
7748 /* Create vector. */
7749 state_byte_size = (description->query_units_num + 7) / 8;
7750 reserved_units_size = (VEC_length (state_t, output_states_vect)
7751 * state_byte_size);
7753 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7755 for (i = 0; i < reserved_units_size; i++)
7756 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7757 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7759 state_t s = VEC_index (state_t, output_states_vect, n);
7760 for (i = 0; i < description->units_num; i++)
7761 if (units_array [i]->query_p
7762 && first_cycle_unit_presence (s, i))
7764 int ri = (s->order_state_num * state_byte_size
7765 + units_array [i]->query_num / 8);
7766 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7768 x += 1 << (units_array [i]->query_num % 8);
7769 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7772 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7773 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7774 fprintf (output_file, "static const ");
7775 output_range_type (output_file, 0, 255);
7776 fprintf (output_file, " ");
7777 output_reserved_units_table_name (output_file, automaton);
7778 fprintf (output_file, "[] = {\n");
7779 output_vect (reserved_units_table);
7780 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7781 CPU_UNITS_QUERY_MACRO_NAME);
7783 VEC_free (state_t, heap, output_states_vect);
7784 VEC_free (vect_el_t, heap, reserved_units_table);
7787 /* The function outputs all tables representing DFA(s) used for fast
7788 pipeline hazards recognition. */
7789 static void
7790 output_tables (void)
7792 automaton_t automaton;
7794 for (automaton = description->first_automaton;
7795 automaton != NULL;
7796 automaton = automaton->next_automaton)
7798 output_translate_vect (automaton);
7799 output_trans_table (automaton);
7800 output_min_issue_delay_table (automaton);
7801 output_dead_lock_vect (automaton);
7802 output_reserved_units_table (automaton);
7804 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7805 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7808 /* The function outputs definition and value of PHR interface variable
7809 `max_insn_queue_index'. Its value is not less than maximal queue
7810 length needed for the insn scheduler. */
7811 static void
7812 output_max_insn_queue_index_def (void)
7814 int i, max, latency;
7815 decl_t decl;
7817 max = description->max_insn_reserv_cycles;
7818 for (i = 0; i < description->decls_num; i++)
7820 decl = description->decls [i];
7821 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7823 latency = DECL_INSN_RESERV (decl)->default_latency;
7824 if (latency > max)
7825 max = latency;
7827 else if (decl->mode == dm_bypass)
7829 latency = DECL_BYPASS (decl)->latency;
7830 if (latency > max)
7831 max = latency;
7834 for (i = 0; (1 << i) <= max; i++)
7836 gcc_assert (i >= 0);
7837 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7838 (1 << i) - 1);
7841 /* The function outputs switch cases for insn reservations using
7842 function *output_automata_list_code. */
7843 static void
7844 output_insn_code_cases (void (*output_automata_list_code)
7845 (automata_list_el_t))
7847 decl_t decl, decl2;
7848 int i, j;
7850 for (i = 0; i < description->decls_num; i++)
7852 decl = description->decls [i];
7853 if (decl->mode == dm_insn_reserv)
7854 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7856 for (i = 0; i < description->decls_num; i++)
7858 decl = description->decls [i];
7859 if (decl->mode == dm_insn_reserv
7860 && !DECL_INSN_RESERV (decl)->processed_p)
7862 for (j = i; j < description->decls_num; j++)
7864 decl2 = description->decls [j];
7865 if (decl2->mode == dm_insn_reserv
7866 && (DECL_INSN_RESERV (decl2)->important_automata_list
7867 == DECL_INSN_RESERV (decl)->important_automata_list))
7869 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7870 fprintf (output_file, " case %d: /* %s */\n",
7871 DECL_INSN_RESERV (decl2)->insn_num,
7872 DECL_INSN_RESERV (decl2)->name);
7875 (*output_automata_list_code)
7876 (DECL_INSN_RESERV (decl)->important_automata_list);
7882 /* The function outputs a code for evaluation of a minimal delay of
7883 issue of insns which have reservations in given AUTOMATA_LIST. */
7884 static void
7885 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7887 automata_list_el_t el;
7888 automaton_t automaton;
7890 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7892 automaton = el->automaton;
7893 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7894 output_min_issue_delay_vect_name (output_file, automaton);
7895 fprintf (output_file,
7896 (automaton->min_issue_delay_table_compression_factor != 1
7897 ? " [(" : " ["));
7898 output_translate_vect_name (output_file, automaton);
7899 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7900 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7901 output_chip_member_name (output_file, automaton);
7902 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7903 if (automaton->min_issue_delay_table_compression_factor == 1)
7904 fprintf (output_file, "];\n");
7905 else
7907 fprintf (output_file, ") / %d];\n",
7908 automaton->min_issue_delay_table_compression_factor);
7909 fprintf (output_file, " %s = (%s >> (8 - ((",
7910 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7911 output_translate_vect_name (output_file, automaton);
7912 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7913 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7914 output_chip_member_name (output_file, automaton);
7915 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
7916 fprintf
7917 (output_file, " %% %d + 1) * %d)) & %d;\n",
7918 automaton->min_issue_delay_table_compression_factor,
7919 8 / automaton->min_issue_delay_table_compression_factor,
7920 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7921 - 1);
7923 if (el == automata_list)
7924 fprintf (output_file, " %s = %s;\n",
7925 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7926 else
7928 fprintf (output_file, " if (%s > %s)\n",
7929 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7930 fprintf (output_file, " %s = %s;\n",
7931 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7934 fprintf (output_file, " break;\n\n");
7937 /* Output function `internal_min_issue_delay'. */
7938 static void
7939 output_internal_min_issue_delay_func (void)
7941 fprintf (output_file,
7942 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7943 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7944 CHIP_NAME, CHIP_PARAMETER_NAME);
7945 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7946 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7947 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7948 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7949 fprintf (output_file,
7950 "\n default:\n %s = -1;\n break;\n }\n",
7951 RESULT_VARIABLE_NAME);
7952 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7953 fprintf (output_file, "}\n\n");
7956 /* The function outputs a code changing state after issue of insns
7957 which have reservations in given AUTOMATA_LIST. */
7958 static void
7959 output_automata_list_transition_code (automata_list_el_t automata_list)
7961 automata_list_el_t el, next_el;
7963 fprintf (output_file, " {\n");
7964 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7965 for (el = automata_list;; el = next_el)
7967 next_el = el->next_automata_list_el;
7968 if (next_el == NULL)
7969 break;
7970 fprintf (output_file, " ");
7971 output_state_member_type (output_file, el->automaton);
7972 fprintf (output_file, " ");
7973 output_temp_chip_member_name (output_file, el->automaton);
7974 fprintf (output_file, ";\n");
7976 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7977 if (comb_vect_p (el->automaton->trans_table))
7979 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7980 output_trans_base_vect_name (output_file, el->automaton);
7981 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7982 output_chip_member_name (output_file, el->automaton);
7983 fprintf (output_file, "] + ");
7984 output_translate_vect_name (output_file, el->automaton);
7985 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7986 fprintf (output_file, " if (");
7987 output_trans_check_vect_name (output_file, el->automaton);
7988 fprintf (output_file, " [%s] != %s->",
7989 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7990 output_chip_member_name (output_file, el->automaton);
7991 fprintf (output_file, ")\n");
7992 fprintf (output_file, " return %s (%s, %s);\n",
7993 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7994 CHIP_PARAMETER_NAME);
7995 fprintf (output_file, " else\n");
7996 fprintf (output_file, " ");
7997 if (el->next_automata_list_el != NULL)
7998 output_temp_chip_member_name (output_file, el->automaton);
7999 else
8001 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8002 output_chip_member_name (output_file, el->automaton);
8004 fprintf (output_file, " = ");
8005 output_trans_comb_vect_name (output_file, el->automaton);
8006 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8008 else
8010 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8011 output_trans_full_vect_name (output_file, el->automaton);
8012 fprintf (output_file, " [");
8013 output_translate_vect_name (output_file, el->automaton);
8014 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8015 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8016 output_chip_member_name (output_file, el->automaton);
8017 fprintf (output_file, " * %d];\n",
8018 el->automaton->insn_equiv_classes_num);
8019 fprintf (output_file, " if (%s >= %d)\n",
8020 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8021 fprintf (output_file, " return %s (%s, %s);\n",
8022 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8023 CHIP_PARAMETER_NAME);
8024 fprintf (output_file, " else\n ");
8025 if (el->next_automata_list_el != NULL)
8026 output_temp_chip_member_name (output_file, el->automaton);
8027 else
8029 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8030 output_chip_member_name (output_file, el->automaton);
8032 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8034 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8035 for (el = automata_list;; el = next_el)
8037 next_el = el->next_automata_list_el;
8038 if (next_el == NULL)
8039 break;
8040 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8041 output_chip_member_name (output_file, el->automaton);
8042 fprintf (output_file, " = ");
8043 output_temp_chip_member_name (output_file, el->automaton);
8044 fprintf (output_file, ";\n");
8046 fprintf (output_file, " return -1;\n");
8047 fprintf (output_file, " }\n");
8050 /* Output function `internal_state_transition'. */
8051 static void
8052 output_internal_trans_func (void)
8054 fprintf (output_file,
8055 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8056 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8057 CHIP_NAME, CHIP_PARAMETER_NAME);
8058 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8059 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8060 output_insn_code_cases (output_automata_list_transition_code);
8061 fprintf (output_file, "\n default:\n return -1;\n }\n");
8062 fprintf (output_file, "}\n\n");
8065 /* Output code
8067 if (insn != 0)
8069 insn_code = dfa_insn_code (insn);
8070 if (insn_code > DFA__ADVANCE_CYCLE)
8071 return code;
8073 else
8074 insn_code = DFA__ADVANCE_CYCLE;
8076 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8077 code denotes CODE. */
8078 static void
8079 output_internal_insn_code_evaluation (const char *insn_name,
8080 const char *insn_code_name,
8081 int code)
8083 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
8084 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8085 DFA_INSN_CODE_FUNC_NAME, insn_name);
8086 fprintf (output_file, " if (%s > %s)\n return %d;\n",
8087 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8088 fprintf (output_file, " }\n else\n %s = %s;\n\n",
8089 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8093 /* This function outputs `dfa_insn_code' and its helper function
8094 `dfa_insn_code_enlarge'. */
8095 static void
8096 output_dfa_insn_code_func (void)
8098 /* Emacs c-mode gets really confused if there's a { or } in column 0
8099 inside a string, so don't do that. */
8100 fprintf (output_file, "\
8101 static void\n\
8102 dfa_insn_code_enlarge (int uid)\n\
8103 {\n\
8104 int i = %s;\n\
8105 %s = 2 * uid;\n\
8106 %s = XRESIZEVEC (int, %s,\n\
8107 %s);\n\
8108 for (; i < %s; i++)\n\
8109 %s[i] = -1;\n}\n\n",
8110 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8111 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8112 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8113 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8114 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8115 DFA_INSN_CODES_VARIABLE_NAME);
8116 fprintf (output_file, "\
8117 static inline int\n%s (rtx %s)\n\
8118 {\n\
8119 int uid = INSN_UID (%s);\n\
8120 int %s;\n\n",
8121 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8122 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8124 fprintf (output_file,
8125 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8126 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8127 fprintf (output_file, " %s = %s[uid];\n",
8128 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8129 fprintf (output_file, "\
8130 if (%s < 0)\n\
8131 {\n\
8132 %s = %s (%s);\n\
8133 %s[uid] = %s;\n\
8134 }\n",
8135 INTERNAL_INSN_CODE_NAME,
8136 INTERNAL_INSN_CODE_NAME,
8137 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8138 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8139 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8142 /* The function outputs PHR interface function `state_transition'. */
8143 static void
8144 output_trans_func (void)
8146 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8147 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8148 INSN_PARAMETER_NAME);
8149 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8150 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8151 INTERNAL_INSN_CODE_NAME, -1);
8152 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8153 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8156 /* Output function `min_issue_delay'. */
8157 static void
8158 output_min_issue_delay_func (void)
8160 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8161 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8162 INSN_PARAMETER_NAME);
8163 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8164 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8165 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8166 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8167 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8168 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8169 fprintf (output_file, " }\n else\n %s = %s;\n",
8170 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8171 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8172 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8173 CHIP_NAME, STATE_NAME);
8174 fprintf (output_file, "}\n\n");
8177 /* Output function `internal_dead_lock'. */
8178 static void
8179 output_internal_dead_lock_func (void)
8181 automaton_t automaton;
8183 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8184 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8185 fprintf (output_file, "{\n");
8186 for (automaton = description->first_automaton;
8187 automaton != NULL;
8188 automaton = automaton->next_automaton)
8189 if (automaton->locked_states)
8191 fprintf (output_file, " if (");
8192 output_dead_lock_vect_name (output_file, automaton);
8193 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8194 output_chip_member_name (output_file, automaton);
8195 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8197 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8200 /* The function outputs PHR interface function `state_dead_lock_p'. */
8201 static void
8202 output_dead_lock_func (void)
8204 fprintf (output_file, "int\n%s (%s %s)\n",
8205 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8206 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8207 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8210 /* Output function `internal_reset'. */
8211 static void
8212 output_internal_reset_func (void)
8214 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8215 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8216 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8217 CHIP_PARAMETER_NAME, CHIP_NAME);
8220 /* The function outputs PHR interface function `state_size'. */
8221 static void
8222 output_size_func (void)
8224 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8225 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8228 /* The function outputs PHR interface function `state_reset'. */
8229 static void
8230 output_reset_func (void)
8232 fprintf (output_file, "void\n%s (%s %s)\n",
8233 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8234 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8235 CHIP_NAME, STATE_NAME);
8238 /* Output function `min_insn_conflict_delay'. */
8239 static void
8240 output_min_insn_conflict_delay_func (void)
8242 fprintf (output_file,
8243 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8244 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8245 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8246 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8247 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8248 INTERNAL_INSN2_CODE_NAME);
8249 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8250 INTERNAL_INSN_CODE_NAME, 0);
8251 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8252 INTERNAL_INSN2_CODE_NAME, 0);
8253 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8254 CHIP_NAME, STATE_NAME, CHIP_NAME);
8255 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8256 fprintf (output_file, " transition = %s (%s, &%s);\n",
8257 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8258 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8259 fprintf (output_file, " return %s (%s, &%s);\n",
8260 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8261 CHIP_NAME);
8262 fprintf (output_file, "}\n\n");
8265 /* Output the array holding default latency values. These are used in
8266 insn_latency and maximal_insn_latency function implementations. */
8267 static void
8268 output_default_latencies (void)
8270 int i, j, col;
8271 decl_t decl;
8272 const char *tabletype = "unsigned char";
8274 /* Find the smallest integer type that can hold all the default
8275 latency values. */
8276 for (i = 0; i < description->decls_num; i++)
8277 if (description->decls[i]->mode == dm_insn_reserv)
8279 decl = description->decls[i];
8280 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8281 && tabletype[0] != 'i') /* Don't shrink it. */
8282 tabletype = "unsigned short";
8283 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8284 tabletype = "int";
8287 fprintf (output_file, " static const %s default_latencies[] =\n {",
8288 tabletype);
8290 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8291 if (description->decls[i]->mode == dm_insn_reserv
8292 && description->decls[i] != advance_cycle_insn_decl)
8294 if ((col = (col+1) % 8) == 0)
8295 fputs ("\n ", output_file);
8296 decl = description->decls[i];
8297 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8298 fprintf (output_file, "% 4d,",
8299 DECL_INSN_RESERV (decl)->default_latency);
8301 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8302 fputs ("\n };\n", output_file);
8305 /* Output function `internal_insn_latency'. */
8306 static void
8307 output_internal_insn_latency_func (void)
8309 int i;
8310 decl_t decl;
8311 struct bypass_decl *bypass;
8313 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",
8314 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8315 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8316 INSN2_PARAMETER_NAME);
8317 fprintf (output_file, "{\n");
8319 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8321 fputs (" return 0;\n}\n\n", output_file);
8322 return;
8325 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8326 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8327 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8329 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8330 for (i = 0; i < description->decls_num; i++)
8331 if (description->decls[i]->mode == dm_insn_reserv
8332 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8334 decl = description->decls [i];
8335 fprintf (output_file,
8336 " case %d:\n switch (%s)\n {\n",
8337 DECL_INSN_RESERV (decl)->insn_num,
8338 INTERNAL_INSN2_CODE_NAME);
8339 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8340 bypass != NULL;
8341 bypass = bypass->next)
8343 gcc_assert (bypass->in_insn_reserv->insn_num
8344 != (DECL_INSN_RESERV
8345 (advance_cycle_insn_decl)->insn_num));
8346 fprintf (output_file, " case %d:\n",
8347 bypass->in_insn_reserv->insn_num);
8348 for (;;)
8350 if (bypass->bypass_guard_name == NULL)
8352 gcc_assert (bypass->next == NULL
8353 || (bypass->in_insn_reserv
8354 != bypass->next->in_insn_reserv));
8355 fprintf (output_file, " return %d;\n",
8356 bypass->latency);
8358 else
8360 fprintf (output_file,
8361 " if (%s (%s, %s))\n",
8362 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8363 INSN2_PARAMETER_NAME);
8364 fprintf (output_file, " return %d;\n",
8365 bypass->latency);
8367 if (bypass->next == NULL
8368 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8369 break;
8370 bypass = bypass->next;
8372 if (bypass->bypass_guard_name != NULL)
8373 fprintf (output_file, " break;\n");
8375 fputs (" }\n break;\n", output_file);
8378 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8379 INTERNAL_INSN_CODE_NAME);
8382 /* Output function `internal_maximum_insn_latency'. */
8383 static void
8384 output_internal_maximal_insn_latency_func (void)
8386 decl_t decl;
8387 struct bypass_decl *bypass;
8388 int i;
8389 int max;
8391 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8392 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8393 INSN_PARAMETER_NAME);
8394 fprintf (output_file, "{\n");
8396 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8398 fputs (" return 0;\n}\n\n", output_file);
8399 return;
8402 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8403 for (i = 0; i < description->decls_num; i++)
8404 if (description->decls[i]->mode == dm_insn_reserv
8405 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8407 decl = description->decls [i];
8408 max = DECL_INSN_RESERV (decl)->default_latency;
8409 fprintf (output_file,
8410 " case %d: {",
8411 DECL_INSN_RESERV (decl)->insn_num);
8412 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8413 bypass != NULL;
8414 bypass = bypass->next)
8416 if (bypass->latency > max)
8417 max = bypass->latency;
8419 fprintf (output_file, " return %d; }\n break;\n", max);
8422 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8423 INTERNAL_INSN_CODE_NAME);
8426 /* The function outputs PHR interface function `insn_latency'. */
8427 static void
8428 output_insn_latency_func (void)
8430 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8431 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8432 fprintf (output_file, "{\n int %s, %s;\n",
8433 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8434 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8435 INTERNAL_INSN_CODE_NAME, 0);
8436 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8437 INTERNAL_INSN2_CODE_NAME, 0);
8438 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8439 INTERNAL_INSN_LATENCY_FUNC_NAME,
8440 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8441 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8444 /* The function outputs PHR interface function `maximal_insn_latency'. */
8445 static void
8446 output_maximal_insn_latency_func (void)
8448 fprintf (output_file, "int\n%s (rtx %s)\n",
8449 "maximal_insn_latency", INSN_PARAMETER_NAME);
8450 fprintf (output_file, "{\n int %s;\n",
8451 INTERNAL_INSN_CODE_NAME);
8452 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8453 INTERNAL_INSN_CODE_NAME, 0);
8454 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8455 "internal_maximal_insn_latency",
8456 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8459 /* The function outputs PHR interface function `print_reservation'. */
8460 static void
8461 output_print_reservation_func (void)
8463 decl_t decl;
8464 int i, j;
8466 fprintf (output_file,
8467 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8468 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8469 INSN_PARAMETER_NAME);
8471 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8473 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8474 NOTHING_NAME, FILE_PARAMETER_NAME);
8475 return;
8479 fputs (" static const char *const reservation_names[] =\n {",
8480 output_file);
8482 for (i = 0, j = 0; i < description->decls_num; i++)
8484 decl = description->decls [i];
8485 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8487 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8488 j++;
8490 fprintf (output_file, "\n \"%s\",",
8491 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8492 finish_regexp_representation ();
8495 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8497 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8498 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8500 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8501 INSN_PARAMETER_NAME,
8502 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8503 fprintf (output_file, " else\n\
8504 {\n\
8505 %s = %s (%s);\n\
8506 if (%s > %s)\n\
8507 %s = %s;\n\
8508 }\n",
8509 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8510 INSN_PARAMETER_NAME,
8511 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8512 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8514 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8515 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8518 /* The following function is used to sort unit declaration by their
8519 names. */
8520 static int
8521 units_cmp (const void *unit1, const void *unit2)
8523 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8524 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8526 return strcmp (u1->name, u2->name);
8529 /* The following macro value is name of struct containing unit name
8530 and unit code. */
8531 #define NAME_CODE_STRUCT_NAME "name_code"
8533 /* The following macro value is name of table of struct name_code. */
8534 #define NAME_CODE_TABLE_NAME "name_code_table"
8536 /* The following macro values are member names for struct name_code. */
8537 #define NAME_MEMBER_NAME "name"
8538 #define CODE_MEMBER_NAME "code"
8540 /* The following macro values are local variable names for function
8541 `get_cpu_unit_code'. */
8542 #define CMP_VARIABLE_NAME "cmp"
8543 #define LOW_VARIABLE_NAME "l"
8544 #define MIDDLE_VARIABLE_NAME "m"
8545 #define HIGH_VARIABLE_NAME "h"
8547 /* The following function outputs function to obtain internal cpu unit
8548 code by the cpu unit name. */
8549 static void
8550 output_get_cpu_unit_code_func (void)
8552 int i;
8553 unit_decl_t *units;
8555 fprintf (output_file, "int\n%s (const char *%s)\n",
8556 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8557 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8558 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8559 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8560 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8561 fprintf (output_file, " static struct %s %s [] =\n {\n",
8562 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8563 units = XNEWVEC (unit_decl_t, description->units_num);
8564 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8565 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8566 for (i = 0; i < description->units_num; i++)
8567 if (units [i]->query_p)
8568 fprintf (output_file, " {\"%s\", %d},\n",
8569 units[i]->name, units[i]->query_num);
8570 fprintf (output_file, " };\n\n");
8571 fprintf (output_file, " /* The following is binary search: */\n");
8572 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8573 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8574 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8575 fprintf (output_file, " while (%s <= %s)\n {\n",
8576 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8577 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8578 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8579 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8580 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8581 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8582 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8583 fprintf (output_file, " %s = %s - 1;\n",
8584 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8585 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8586 fprintf (output_file, " %s = %s + 1;\n",
8587 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8588 fprintf (output_file, " else\n");
8589 fprintf (output_file, " return %s [%s].%s;\n }\n",
8590 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8591 fprintf (output_file, " return -1;\n}\n\n");
8592 free (units);
8595 /* The following function outputs function to check reservation of cpu
8596 unit (its internal code will be passed as the function argument) in
8597 given cpu state. */
8598 static void
8599 output_cpu_unit_reservation_p (void)
8601 automaton_t automaton;
8603 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8604 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8605 STATE_TYPE_NAME, STATE_NAME,
8606 CPU_CODE_PARAMETER_NAME);
8607 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8608 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8609 description->query_units_num);
8610 if (description->query_units_num > 0)
8611 for (automaton = description->first_automaton;
8612 automaton != NULL;
8613 automaton = automaton->next_automaton)
8615 fprintf (output_file, " if ((");
8616 output_reserved_units_table_name (output_file, automaton);
8617 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8618 output_chip_member_name (output_file, automaton);
8619 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8620 (description->query_units_num + 7) / 8,
8621 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8622 fprintf (output_file, " return 1;\n");
8624 fprintf (output_file, " return 0;\n}\n\n");
8627 /* The following function outputs a function to check if insn
8628 has a dfa reservation. */
8629 static void
8630 output_insn_has_dfa_reservation_p (void)
8632 fprintf (output_file,
8633 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8634 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8635 INSN_PARAMETER_NAME);
8637 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8639 fprintf (output_file, " return false;\n}\n\n");
8640 return;
8643 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8645 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8646 INSN_PARAMETER_NAME,
8647 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8648 fprintf (output_file, " else\n\
8649 {\n\
8650 %s = %s (%s);\n\
8651 if (%s > %s)\n\
8652 %s = %s;\n\
8653 }\n\n",
8654 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8655 INSN_PARAMETER_NAME,
8656 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8657 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8659 fprintf (output_file, " return %s != %s;\n}\n\n",
8660 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8663 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8664 and 'dfa_clear_single_insn_cache'. */
8665 static void
8666 output_dfa_clean_insn_cache_func (void)
8668 fprintf (output_file,
8669 "void\n%s (void)\n{\n int %s;\n\n",
8670 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8671 fprintf (output_file,
8672 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8673 I_VARIABLE_NAME, I_VARIABLE_NAME,
8674 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8675 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8677 fprintf (output_file,
8678 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8679 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8680 I_VARIABLE_NAME);
8681 fprintf (output_file,
8682 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8683 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8684 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8685 I_VARIABLE_NAME);
8688 /* The function outputs PHR interface function `dfa_start'. */
8689 static void
8690 output_dfa_start_func (void)
8692 fprintf (output_file,
8693 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8694 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8695 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8696 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8697 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8700 /* The function outputs PHR interface function `dfa_finish'. */
8701 static void
8702 output_dfa_finish_func (void)
8704 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8705 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8710 /* The page contains code for output description file (readable
8711 representation of original description and generated DFA(s). */
8713 /* The function outputs string representation of IR reservation. */
8714 static void
8715 output_regexp (regexp_t regexp)
8717 fprintf (output_description_file, "%s", regexp_representation (regexp));
8718 finish_regexp_representation ();
8721 /* Output names of units in LIST separated by comma. */
8722 static void
8723 output_unit_set_el_list (unit_set_el_t list)
8725 unit_set_el_t el;
8727 for (el = list; el != NULL; el = el->next_unit_set_el)
8729 if (el != list)
8730 fprintf (output_description_file, ", ");
8731 fprintf (output_description_file, "%s", el->unit_decl->name);
8735 /* Output patterns in LIST separated by comma. */
8736 static void
8737 output_pattern_set_el_list (pattern_set_el_t list)
8739 pattern_set_el_t el;
8740 int i;
8742 for (el = list; el != NULL; el = el->next_pattern_set_el)
8744 if (el != list)
8745 fprintf (output_description_file, ", ");
8746 for (i = 0; i < el->units_num; i++)
8747 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8748 el->unit_decls [i]->name);
8752 /* The function outputs string representation of IR define_reservation
8753 and define_insn_reservation. */
8754 static void
8755 output_description (void)
8757 decl_t decl;
8758 int i;
8760 for (i = 0; i < description->decls_num; i++)
8762 decl = description->decls [i];
8763 if (decl->mode == dm_unit)
8765 if (DECL_UNIT (decl)->excl_list != NULL)
8767 fprintf (output_description_file, "unit %s exclusion_set: ",
8768 DECL_UNIT (decl)->name);
8769 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8770 fprintf (output_description_file, "\n");
8772 if (DECL_UNIT (decl)->presence_list != NULL)
8774 fprintf (output_description_file, "unit %s presence_set: ",
8775 DECL_UNIT (decl)->name);
8776 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8777 fprintf (output_description_file, "\n");
8779 if (DECL_UNIT (decl)->final_presence_list != NULL)
8781 fprintf (output_description_file, "unit %s final_presence_set: ",
8782 DECL_UNIT (decl)->name);
8783 output_pattern_set_el_list
8784 (DECL_UNIT (decl)->final_presence_list);
8785 fprintf (output_description_file, "\n");
8787 if (DECL_UNIT (decl)->absence_list != NULL)
8789 fprintf (output_description_file, "unit %s absence_set: ",
8790 DECL_UNIT (decl)->name);
8791 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8792 fprintf (output_description_file, "\n");
8794 if (DECL_UNIT (decl)->final_absence_list != NULL)
8796 fprintf (output_description_file, "unit %s final_absence_set: ",
8797 DECL_UNIT (decl)->name);
8798 output_pattern_set_el_list
8799 (DECL_UNIT (decl)->final_absence_list);
8800 fprintf (output_description_file, "\n");
8804 fprintf (output_description_file, "\n");
8805 for (i = 0; i < description->decls_num; i++)
8807 decl = description->decls [i];
8808 if (decl->mode == dm_reserv)
8810 fprintf (output_description_file, "reservation %s: ",
8811 DECL_RESERV (decl)->name);
8812 output_regexp (DECL_RESERV (decl)->regexp);
8813 fprintf (output_description_file, "\n");
8815 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8817 fprintf (output_description_file, "insn reservation %s ",
8818 DECL_INSN_RESERV (decl)->name);
8819 print_rtl (output_description_file,
8820 DECL_INSN_RESERV (decl)->condexp);
8821 fprintf (output_description_file, ": ");
8822 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8823 fprintf (output_description_file, "\n");
8825 else if (decl->mode == dm_bypass)
8826 fprintf (output_description_file, "bypass %d %s %s\n",
8827 DECL_BYPASS (decl)->latency,
8828 DECL_BYPASS (decl)->out_pattern,
8829 DECL_BYPASS (decl)->in_pattern);
8831 fprintf (output_description_file, "\n\f\n");
8834 /* The function outputs name of AUTOMATON. */
8835 static void
8836 output_automaton_name (FILE *f, automaton_t automaton)
8838 if (automaton->corresponding_automaton_decl == NULL)
8839 fprintf (f, "#%d", automaton->automaton_order_num);
8840 else
8841 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8844 /* Maximal length of line for pretty printing into description
8845 file. */
8846 #define MAX_LINE_LENGTH 70
8848 /* The function outputs units name belonging to AUTOMATON. */
8849 static void
8850 output_automaton_units (automaton_t automaton)
8852 decl_t decl;
8853 const char *name;
8854 int curr_line_length;
8855 int there_is_an_automaton_unit;
8856 int i;
8858 fprintf (output_description_file, "\n Corresponding units:\n");
8859 fprintf (output_description_file, " ");
8860 curr_line_length = 4;
8861 there_is_an_automaton_unit = 0;
8862 for (i = 0; i < description->decls_num; i++)
8864 decl = description->decls [i];
8865 if (decl->mode == dm_unit
8866 && (DECL_UNIT (decl)->corresponding_automaton_num
8867 == automaton->automaton_order_num))
8869 there_is_an_automaton_unit = 1;
8870 name = DECL_UNIT (decl)->name;
8871 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8873 curr_line_length = strlen (name) + 4;
8874 fprintf (output_description_file, "\n ");
8876 else
8878 curr_line_length += strlen (name) + 1;
8879 fprintf (output_description_file, " ");
8881 fprintf (output_description_file, "%s", name);
8884 if (!there_is_an_automaton_unit)
8885 fprintf (output_description_file, "<None>");
8886 fprintf (output_description_file, "\n\n");
8889 /* The following variable is used for forming array of all possible cpu unit
8890 reservations described by the current DFA state. */
8891 static VEC(reserv_sets_t, heap) *state_reservs;
8893 /* The function forms `state_reservs' for STATE. */
8894 static void
8895 add_state_reservs (state_t state)
8897 alt_state_t curr_alt_state;
8899 if (state->component_states != NULL)
8900 for (curr_alt_state = state->component_states;
8901 curr_alt_state != NULL;
8902 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8903 add_state_reservs (curr_alt_state->state);
8904 else
8905 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
8908 /* The function outputs readable representation of all out arcs of
8909 STATE. */
8910 static void
8911 output_state_arcs (state_t state)
8913 arc_t arc;
8914 ainsn_t ainsn;
8915 const char *insn_name;
8916 int curr_line_length;
8918 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8920 ainsn = arc->insn;
8921 gcc_assert (ainsn->first_insn_with_same_reservs);
8922 fprintf (output_description_file, " ");
8923 curr_line_length = 7;
8924 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8927 insn_name = ainsn->insn_reserv_decl->name;
8928 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8930 if (ainsn != arc->insn)
8932 fprintf (output_description_file, ",\n ");
8933 curr_line_length = strlen (insn_name) + 6;
8935 else
8936 curr_line_length += strlen (insn_name);
8938 else
8940 curr_line_length += strlen (insn_name);
8941 if (ainsn != arc->insn)
8943 curr_line_length += 2;
8944 fprintf (output_description_file, ", ");
8947 fprintf (output_description_file, "%s", insn_name);
8948 ainsn = ainsn->next_same_reservs_insn;
8950 while (ainsn != NULL);
8951 fprintf (output_description_file, " %d \n",
8952 arc->to_state->order_state_num);
8954 fprintf (output_description_file, "\n");
8957 /* The following function is used for sorting possible cpu unit
8958 reservation of a DFA state. */
8959 static int
8960 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8962 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8963 *(const_reserv_sets_t const*) reservs_ptr_2);
8966 /* The following function is used for sorting possible cpu unit
8967 reservation of a DFA state. */
8968 static void
8969 remove_state_duplicate_reservs (void)
8971 size_t i, j;
8973 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8974 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8975 VEC_index (reserv_sets_t, state_reservs, i)))
8977 j++;
8978 VEC_replace (reserv_sets_t, state_reservs, j,
8979 VEC_index (reserv_sets_t, state_reservs, i));
8981 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8984 /* The following function output readable representation of DFA(s)
8985 state used for fast recognition of pipeline hazards. State is
8986 described by possible (current and scheduled) cpu unit
8987 reservations. */
8988 static void
8989 output_state (state_t state)
8991 size_t i;
8993 state_reservs = 0;
8995 fprintf (output_description_file, " State #%d", state->order_state_num);
8996 fprintf (output_description_file,
8997 state->new_cycle_p ? " (new cycle)\n" : "\n");
8998 add_state_reservs (state);
8999 VEC_qsort (reserv_sets_t, state_reservs, state_reservs_cmp);
9000 remove_state_duplicate_reservs ();
9001 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
9003 fprintf (output_description_file, " ");
9004 output_reserv_sets (output_description_file,
9005 VEC_index (reserv_sets_t, state_reservs, i));
9006 fprintf (output_description_file, "\n");
9008 fprintf (output_description_file, "\n");
9009 output_state_arcs (state);
9010 VEC_free (reserv_sets_t, heap, state_reservs);
9013 /* The following function output readable representation of
9014 DFAs used for fast recognition of pipeline hazards. */
9015 static void
9016 output_automaton_descriptions (void)
9018 automaton_t automaton;
9020 for (automaton = description->first_automaton;
9021 automaton != NULL;
9022 automaton = automaton->next_automaton)
9024 fprintf (output_description_file, "\nAutomaton ");
9025 output_automaton_name (output_description_file, automaton);
9026 fprintf (output_description_file, "\n");
9027 output_automaton_units (automaton);
9028 pass_states (automaton, output_state);
9034 /* The page contains top level function for generation DFA(s) used for
9035 PHR. */
9037 /* The function outputs statistics about work of different phases of
9038 DFA generator. */
9039 static void
9040 output_statistics (FILE *f)
9042 automaton_t automaton;
9043 int states_num;
9044 #ifndef NDEBUG
9045 int transition_comb_vect_els = 0;
9046 int transition_full_vect_els = 0;
9047 int min_issue_delay_vect_els = 0;
9048 int locked_states = 0;
9049 #endif
9051 for (automaton = description->first_automaton;
9052 automaton != NULL;
9053 automaton = automaton->next_automaton)
9055 fprintf (f, "\nAutomaton ");
9056 output_automaton_name (f, automaton);
9057 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9058 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9059 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9060 automaton->DFA_states_num, automaton->DFA_arcs_num);
9061 states_num = automaton->DFA_states_num;
9062 if (!no_minimization_flag)
9064 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9065 automaton->minimal_DFA_states_num,
9066 automaton->minimal_DFA_arcs_num);
9067 states_num = automaton->minimal_DFA_states_num;
9069 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9070 description->insns_num, automaton->insn_equiv_classes_num);
9071 fprintf (f, " %d locked states\n", automaton->locked_states);
9072 #ifndef NDEBUG
9073 fprintf
9074 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9075 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9076 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9077 (comb_vect_p (automaton->trans_table)
9078 ? "use comb vect" : "use simple vect"));
9079 fprintf
9080 (f, "%5ld min delay table els, compression factor %d\n",
9081 (long) states_num * automaton->insn_equiv_classes_num,
9082 automaton->min_issue_delay_table_compression_factor);
9083 transition_comb_vect_els
9084 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9085 transition_full_vect_els
9086 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9087 min_issue_delay_vect_els
9088 += states_num * automaton->insn_equiv_classes_num;
9089 locked_states
9090 += automaton->locked_states;
9091 #endif
9093 #ifndef NDEBUG
9094 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9095 allocated_states_num, allocated_arcs_num);
9096 fprintf (f, "%5d all allocated alternative states\n",
9097 allocated_alt_states_num);
9098 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9099 transition_comb_vect_els, transition_full_vect_els);
9100 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9101 fprintf (f, "%5d all locked states\n", locked_states);
9102 #endif
9105 /* The function output times of work of different phases of DFA
9106 generator. */
9107 static void
9108 output_time_statistics (FILE *f)
9110 fprintf (f, "\n transformation: ");
9111 print_active_time (f, transform_time);
9112 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9113 print_active_time (f, NDFA_time);
9114 if (ndfa_flag)
9116 fprintf (f, ", NDFA -> DFA: ");
9117 print_active_time (f, NDFA_to_DFA_time);
9119 fprintf (f, "\n DFA minimization: ");
9120 print_active_time (f, minimize_time);
9121 fprintf (f, ", making insn equivalence: ");
9122 print_active_time (f, equiv_time);
9123 fprintf (f, "\n all automaton generation: ");
9124 print_active_time (f, automaton_generation_time);
9125 fprintf (f, ", output: ");
9126 print_active_time (f, output_time);
9127 fprintf (f, "\n");
9130 /* The function generates DFA (deterministic finite state automaton)
9131 for fast recognition of pipeline hazards. No errors during
9132 checking must be fixed before this function call. */
9133 static void
9134 generate (void)
9136 automata_num = split_argument;
9137 if (description->units_num < automata_num)
9138 automata_num = description->units_num;
9139 initiate_states ();
9140 initiate_arcs ();
9141 initiate_automata_lists ();
9142 initiate_pass_states ();
9143 initiate_excl_sets ();
9144 initiate_presence_absence_pattern_sets ();
9145 automaton_generation_time = create_ticker ();
9146 create_automata ();
9147 ticker_off (&automaton_generation_time);
9152 /* This page mainly contains top level functions of pipeline hazards
9153 description translator. */
9155 /* The following macro value is suffix of name of description file of
9156 pipeline hazards description translator. */
9157 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9159 /* The function returns suffix of given file name. The returned
9160 string can not be changed. */
9161 static const char *
9162 file_name_suffix (const char *file_name)
9164 const char *last_period;
9166 for (last_period = NULL; *file_name != '\0'; file_name++)
9167 if (*file_name == '.')
9168 last_period = file_name;
9169 return (last_period == NULL ? file_name : last_period);
9172 /* The function returns base name of given file name, i.e. pointer to
9173 first char after last `/' (or `\' for WIN32) in given file name,
9174 given file name itself if the directory name is absent. The
9175 returned string can not be changed. */
9176 static const char *
9177 base_file_name (const char *file_name)
9179 int directory_name_length;
9181 directory_name_length = strlen (file_name);
9182 #ifdef WIN32
9183 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9184 && file_name[directory_name_length] != '\\')
9185 #else
9186 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9187 #endif
9188 directory_name_length--;
9189 return file_name + directory_name_length + 1;
9192 /* The following is top level function to initialize the work of
9193 pipeline hazards description translator. */
9194 static void
9195 initiate_automaton_gen (int argc, char **argv)
9197 const char *base_name;
9198 int i;
9200 ndfa_flag = 0;
9201 split_argument = 0; /* default value */
9202 no_minimization_flag = 0;
9203 time_flag = 0;
9204 stats_flag = 0;
9205 v_flag = 0;
9206 w_flag = 0;
9207 progress_flag = 0;
9208 for (i = 2; i < argc; i++)
9209 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9210 no_minimization_flag = 1;
9211 else if (strcmp (argv [i], TIME_OPTION) == 0)
9212 time_flag = 1;
9213 else if (strcmp (argv [i], STATS_OPTION) == 0)
9214 stats_flag = 1;
9215 else if (strcmp (argv [i], V_OPTION) == 0)
9216 v_flag = 1;
9217 else if (strcmp (argv [i], W_OPTION) == 0)
9218 w_flag = 1;
9219 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9220 ndfa_flag = 1;
9221 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9222 progress_flag = 1;
9223 else if (strcmp (argv [i], "-split") == 0)
9225 if (i + 1 >= argc)
9226 fatal ("-split has no argument.");
9227 fatal ("option `-split' has not been implemented yet\n");
9228 /* split_argument = atoi (argument_vect [i + 1]); */
9231 /* Initialize IR storage. */
9232 obstack_init (&irp);
9233 initiate_automaton_decl_table ();
9234 initiate_insn_decl_table ();
9235 initiate_decl_table ();
9236 output_file = stdout;
9237 output_description_file = NULL;
9238 base_name = base_file_name (argv[1]);
9239 obstack_grow (&irp, base_name,
9240 strlen (base_name) - strlen (file_name_suffix (base_name)));
9241 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9242 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9243 obstack_1grow (&irp, '\0');
9244 output_description_file_name = obstack_base (&irp);
9245 obstack_finish (&irp);
9248 /* The following function checks existence at least one arc marked by
9249 each insn. */
9250 static void
9251 check_automata_insn_issues (void)
9253 automaton_t automaton;
9254 ainsn_t ainsn, reserv_ainsn;
9256 for (automaton = description->first_automaton;
9257 automaton != NULL;
9258 automaton = automaton->next_automaton)
9260 for (ainsn = automaton->ainsn_list;
9261 ainsn != NULL;
9262 ainsn = ainsn->next_ainsn)
9263 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9265 for (reserv_ainsn = ainsn;
9266 reserv_ainsn != NULL;
9267 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9268 if (automaton->corresponding_automaton_decl != NULL)
9270 if (!w_flag)
9271 error ("Automaton `%s': Insn `%s' will never be issued",
9272 automaton->corresponding_automaton_decl->name,
9273 reserv_ainsn->insn_reserv_decl->name);
9274 else
9275 warning ("Automaton `%s': Insn `%s' will never be issued",
9276 automaton->corresponding_automaton_decl->name,
9277 reserv_ainsn->insn_reserv_decl->name);
9279 else
9281 if (!w_flag)
9282 error ("Insn `%s' will never be issued",
9283 reserv_ainsn->insn_reserv_decl->name);
9284 else
9285 warning ("Insn `%s' will never be issued",
9286 reserv_ainsn->insn_reserv_decl->name);
9292 /* The following vla is used for storing pointers to all achieved
9293 states. */
9294 static VEC(state_t, heap) *automaton_states;
9296 /* This function is called by function pass_states to add an achieved
9297 STATE. */
9298 static void
9299 add_automaton_state (state_t state)
9301 VEC_safe_push (state_t, heap, automaton_states, state);
9304 /* The following function forms list of important automata (whose
9305 states may be changed after the insn issue) for each insn. */
9306 static void
9307 form_important_insn_automata_lists (void)
9309 automaton_t automaton;
9310 decl_t decl;
9311 ainsn_t ainsn;
9312 arc_t arc;
9313 int i;
9314 size_t n;
9316 automaton_states = 0;
9317 /* Mark important ainsns. */
9318 for (automaton = description->first_automaton;
9319 automaton != NULL;
9320 automaton = automaton->next_automaton)
9322 VEC_truncate (state_t, automaton_states, 0);
9323 pass_states (automaton, add_automaton_state);
9324 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9326 state_t s = VEC_index (state_t, automaton_states, n);
9327 for (arc = first_out_arc (s);
9328 arc != NULL;
9329 arc = next_out_arc (arc))
9330 if (arc->to_state != s)
9332 gcc_assert (arc->insn->first_insn_with_same_reservs);
9333 for (ainsn = arc->insn;
9334 ainsn != NULL;
9335 ainsn = ainsn->next_same_reservs_insn)
9336 ainsn->important_p = TRUE;
9340 VEC_free (state_t, heap, automaton_states);
9342 /* Create automata sets for the insns. */
9343 for (i = 0; i < description->decls_num; i++)
9345 decl = description->decls [i];
9346 if (decl->mode == dm_insn_reserv)
9348 automata_list_start ();
9349 for (automaton = description->first_automaton;
9350 automaton != NULL;
9351 automaton = automaton->next_automaton)
9352 for (ainsn = automaton->ainsn_list;
9353 ainsn != NULL;
9354 ainsn = ainsn->next_ainsn)
9355 if (ainsn->important_p
9356 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9358 automata_list_add (automaton);
9359 break;
9361 DECL_INSN_RESERV (decl)->important_automata_list
9362 = automata_list_finish ();
9368 /* The following is top level function to generate automat(a,on) for
9369 fast recognition of pipeline hazards. */
9370 static void
9371 expand_automata (void)
9373 int i;
9375 description = XCREATENODEVAR (struct description,
9376 sizeof (struct description)
9377 /* One entry for cycle advancing insn. */
9378 + sizeof (decl_t) * VEC_length (decl_t, decls));
9379 description->decls_num = VEC_length (decl_t, decls);
9380 description->query_units_num = 0;
9381 for (i = 0; i < description->decls_num; i++)
9383 description->decls [i] = VEC_index (decl_t, decls, i);
9384 if (description->decls [i]->mode == dm_unit
9385 && DECL_UNIT (description->decls [i])->query_p)
9386 DECL_UNIT (description->decls [i])->query_num
9387 = description->query_units_num++;
9389 all_time = create_ticker ();
9390 check_time = create_ticker ();
9391 if (progress_flag)
9392 fprintf (stderr, "Check description...");
9393 check_all_description ();
9394 if (progress_flag)
9395 fprintf (stderr, "done\n");
9396 ticker_off (&check_time);
9397 generation_time = create_ticker ();
9398 if (!have_error)
9400 transform_insn_regexps ();
9401 check_unit_distributions_to_automata ();
9403 if (!have_error)
9405 generate ();
9406 check_automata_insn_issues ();
9408 if (!have_error)
9410 form_important_insn_automata_lists ();
9412 ticker_off (&generation_time);
9415 /* The following is top level function to output PHR and to finish
9416 work with pipeline description translator. */
9417 static void
9418 write_automata (void)
9420 output_time = create_ticker ();
9421 if (progress_flag)
9422 fprintf (stderr, "Forming and outputting automata tables...");
9423 output_tables ();
9424 if (progress_flag)
9426 fprintf (stderr, "done\n");
9427 fprintf (stderr, "Output functions to work with automata...");
9429 output_chip_definitions ();
9430 output_max_insn_queue_index_def ();
9431 output_internal_min_issue_delay_func ();
9432 output_internal_trans_func ();
9433 /* Cache of insn dfa codes: */
9434 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9435 fprintf (output_file, "\nstatic int %s;\n\n",
9436 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9437 output_dfa_insn_code_func ();
9438 output_trans_func ();
9439 output_min_issue_delay_func ();
9440 output_internal_dead_lock_func ();
9441 output_dead_lock_func ();
9442 output_size_func ();
9443 output_internal_reset_func ();
9444 output_reset_func ();
9445 output_min_insn_conflict_delay_func ();
9446 output_default_latencies ();
9447 output_internal_insn_latency_func ();
9448 output_insn_latency_func ();
9449 output_internal_maximal_insn_latency_func ();
9450 output_maximal_insn_latency_func ();
9451 output_print_reservation_func ();
9452 /* Output function get_cpu_unit_code. */
9453 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9454 output_get_cpu_unit_code_func ();
9455 output_cpu_unit_reservation_p ();
9456 output_insn_has_dfa_reservation_p ();
9457 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9458 CPU_UNITS_QUERY_MACRO_NAME);
9459 output_dfa_clean_insn_cache_func ();
9460 output_dfa_start_func ();
9461 output_dfa_finish_func ();
9462 if (progress_flag)
9463 fprintf (stderr, "done\n");
9464 if (v_flag)
9466 output_description_file = fopen (output_description_file_name, "w");
9467 if (output_description_file == NULL)
9469 perror (output_description_file_name);
9470 exit (FATAL_EXIT_CODE);
9472 if (progress_flag)
9473 fprintf (stderr, "Output automata description...");
9474 output_description ();
9475 output_automaton_descriptions ();
9476 if (progress_flag)
9477 fprintf (stderr, "done\n");
9478 output_statistics (output_description_file);
9480 if (stats_flag)
9481 output_statistics (stderr);
9482 ticker_off (&output_time);
9483 if (time_flag)
9484 output_time_statistics (stderr);
9485 finish_states ();
9486 finish_arcs ();
9487 finish_automata_lists ();
9488 if (time_flag)
9490 fprintf (stderr, "Summary:\n");
9491 fprintf (stderr, " check time ");
9492 print_active_time (stderr, check_time);
9493 fprintf (stderr, ", generation time ");
9494 print_active_time (stderr, generation_time);
9495 fprintf (stderr, ", all time ");
9496 print_active_time (stderr, all_time);
9497 fprintf (stderr, "\n");
9499 /* Finish all work. */
9500 if (output_description_file != NULL)
9502 fflush (output_description_file);
9503 if (ferror (stdout) != 0)
9504 fatal ("Error in writing DFA description file %s: %s",
9505 output_description_file_name, xstrerror (errno));
9506 fclose (output_description_file);
9508 finish_automaton_decl_table ();
9509 finish_insn_decl_table ();
9510 finish_decl_table ();
9511 obstack_free (&irp, NULL);
9512 if (have_error && output_description_file != NULL)
9513 remove (output_description_file_name);
9517 main (int argc, char **argv)
9519 rtx desc;
9521 progname = "genautomata";
9523 if (!init_rtx_reader_args (argc, argv))
9524 return (FATAL_EXIT_CODE);
9526 initiate_automaton_gen (argc, argv);
9527 while (1)
9529 int lineno;
9530 int insn_code_number;
9532 desc = read_md_rtx (&lineno, &insn_code_number);
9533 if (desc == NULL)
9534 break;
9536 switch (GET_CODE (desc))
9538 case DEFINE_CPU_UNIT:
9539 gen_cpu_unit (desc);
9540 break;
9542 case DEFINE_QUERY_CPU_UNIT:
9543 gen_query_cpu_unit (desc);
9544 break;
9546 case DEFINE_BYPASS:
9547 gen_bypass (desc);
9548 break;
9550 case EXCLUSION_SET:
9551 gen_excl_set (desc);
9552 break;
9554 case PRESENCE_SET:
9555 gen_presence_set (desc);
9556 break;
9558 case FINAL_PRESENCE_SET:
9559 gen_final_presence_set (desc);
9560 break;
9562 case ABSENCE_SET:
9563 gen_absence_set (desc);
9564 break;
9566 case FINAL_ABSENCE_SET:
9567 gen_final_absence_set (desc);
9568 break;
9570 case DEFINE_AUTOMATON:
9571 gen_automaton (desc);
9572 break;
9574 case AUTOMATA_OPTION:
9575 gen_automata_option (desc);
9576 break;
9578 case DEFINE_RESERVATION:
9579 gen_reserv (desc);
9580 break;
9582 case DEFINE_INSN_RESERVATION:
9583 gen_insn_reserv (desc);
9584 break;
9586 default:
9587 break;
9591 if (have_error)
9592 return FATAL_EXIT_CODE;
9594 if (VEC_length (decl_t, decls) > 0)
9596 expand_automata ();
9597 if (!have_error)
9599 puts ("/* Generated automatically by the program `genautomata'\n"
9600 " from the machine description file `md'. */\n\n"
9601 "#include \"config.h\"\n"
9602 "#include \"system.h\"\n"
9603 "#include \"coretypes.h\"\n"
9604 "#include \"tm.h\"\n"
9605 "#include \"rtl.h\"\n"
9606 "#include \"tm_p.h\"\n"
9607 "#include \"insn-config.h\"\n"
9608 "#include \"recog.h\"\n"
9609 "#include \"regs.h\"\n"
9610 "#include \"output.h\"\n"
9611 "#include \"insn-attr.h\"\n"
9612 "#include \"diagnostic-core.h\"\n"
9613 "#include \"flags.h\"\n"
9614 "#include \"function.h\"\n"
9615 "#include \"emit-rtl.h\"\n");
9616 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9618 write_automata ();
9621 else
9623 puts ("/* Generated automatically by the program `genautomata'\n"
9624 " from the machine description file `md'. */\n\n"
9625 "/* There is no automaton, but ISO C forbids empty\n"
9626 " translation units, so include a header file with some\n"
9627 " declarations, and its pre-requisite header file. */\n"
9628 "#include \"config.h\"\n"
9629 "#include \"system.h\"\n");
9632 fflush (stdout);
9633 return (ferror (stdout) != 0 || have_error
9634 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);