PR libstdc++/54577
[official-gcc.git] / gcc / genautomata.c
blob46a398d1a6ec64a69758f75279551aec4ed1803a
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 COLLAPSE_OPTION "-collapse-ndfa"
256 #define NO_COMB_OPTION "-no-comb-vect"
257 #define PROGRESS_OPTION "-progress"
259 /* The following flags are set up by function `initiate_automaton_gen'. */
261 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
262 static int ndfa_flag;
264 /* When making an NDFA, produce additional transitions that collapse
265 NDFA state into a deterministic one suitable for querying CPU units.
266 Provide avance-state transitions only for deterministic states. */
267 static int collapse_flag;
269 /* Do not make minimization of DFA (`-no-minimization'). */
270 static int no_minimization_flag;
272 /* Do not try to generate a comb vector (`-no-comb-vect'). */
273 static int no_comb_flag;
275 /* Value of this variable is number of automata being generated. The
276 actual number of automata may be less this value if there is not
277 sufficient number of units. This value is defined by argument of
278 option `-split' or by constructions automaton if the value is zero
279 (it is default value of the argument). */
280 static int split_argument;
282 /* Flag of output time statistics (`-time'). */
283 static int time_flag;
285 /* Flag of automata statistics (`-stats'). */
286 static int stats_flag;
288 /* Flag of creation of description file which contains description of
289 result automaton and statistics information (`-v'). */
290 static int v_flag;
292 /* Flag of output of a progress bar showing how many states were
293 generated so far for automaton being processed (`-progress'). */
294 static int progress_flag;
296 /* Flag of generating warning instead of error for non-critical errors
297 (`-w'). */
298 static int w_flag;
301 /* Output file for pipeline hazard recognizer (PHR) being generated.
302 The value is NULL if the file is not defined. */
303 static FILE *output_file;
305 /* Description file of PHR. The value is NULL if the file is not
306 created. */
307 static FILE *output_description_file;
309 /* PHR description file name. */
310 static char *output_description_file_name;
312 /* Value of the following variable is node representing description
313 being processed. This is start point of IR. */
314 static struct description *description;
318 /* This page contains description of IR structure (nodes). */
320 enum decl_mode
322 dm_unit,
323 dm_bypass,
324 dm_automaton,
325 dm_excl,
326 dm_presence,
327 dm_absence,
328 dm_reserv,
329 dm_insn_reserv
332 /* This describes define_cpu_unit and define_query_cpu_unit (see file
333 rtl.def). */
334 struct unit_decl
336 const char *name;
337 /* NULL if the automaton name is absent. */
338 const char *automaton_name;
339 /* If the following value is not zero, the cpu unit reservation is
340 described in define_query_cpu_unit. */
341 char query_p;
343 /* The following fields are defined by checker. */
345 /* The following field value is nonzero if the unit is used in an
346 regexp. */
347 char unit_is_used;
349 /* The following field value is order number (0, 1, ...) of given
350 unit. */
351 int unit_num;
352 /* The following field value is corresponding declaration of
353 automaton which was given in description. If the field value is
354 NULL then automaton in the unit declaration was absent. */
355 struct automaton_decl *automaton_decl;
356 /* The following field value is maximal cycle number (1, ...) on
357 which given unit occurs in insns. Zero value means that given
358 unit is not used in insns. */
359 int max_occ_cycle_num;
360 /* The following field value is minimal cycle number (0, ...) on
361 which given unit occurs in insns. -1 value means that given
362 unit is not used in insns. */
363 int min_occ_cycle_num;
364 /* The following list contains units which conflict with given
365 unit. */
366 unit_set_el_t excl_list;
367 /* The following list contains patterns which are required to
368 reservation of given unit. */
369 pattern_set_el_t presence_list;
370 pattern_set_el_t final_presence_list;
371 /* The following list contains patterns which should be not present
372 in reservation for given unit. */
373 pattern_set_el_t absence_list;
374 pattern_set_el_t final_absence_list;
375 /* The following is used only when `query_p' has nonzero value.
376 This is query number for the unit. */
377 int query_num;
378 /* The following is the last cycle on which the unit was checked for
379 correct distributions of units to automata in a regexp. */
380 int last_distribution_check_cycle;
382 /* The following fields are defined by automaton generator. */
384 /* The following field value is number of the automaton to which
385 given unit belongs. */
386 int corresponding_automaton_num;
387 /* If the following value is not zero, the cpu unit is present in a
388 `exclusion_set' or in right part of a `presence_set',
389 `final_presence_set', `absence_set', and
390 `final_absence_set'define_query_cpu_unit. */
391 char in_set_p;
394 /* This describes define_bypass (see file rtl.def). */
395 struct bypass_decl
397 int latency;
398 const char *out_pattern;
399 const char *in_pattern;
400 const char *bypass_guard_name;
402 /* The following fields are defined by checker. */
404 /* output and input insns of given bypass. */
405 struct insn_reserv_decl *out_insn_reserv;
406 struct insn_reserv_decl *in_insn_reserv;
407 /* The next bypass for given output insn. */
408 struct bypass_decl *next;
411 /* This describes define_automaton (see file rtl.def). */
412 struct automaton_decl
414 const char *name;
416 /* The following fields are defined by automaton generator. */
418 /* The following field value is nonzero if the automaton is used in
419 an regexp definition. */
420 char automaton_is_used;
422 /* The following fields are defined by checker. */
424 /* The following field value is the corresponding automaton. This
425 field is not NULL only if the automaton is present in unit
426 declarations and the automatic partition on automata is not
427 used. */
428 automaton_t corresponding_automaton;
431 /* This describes exclusion relations: exclusion_set (see file
432 rtl.def). */
433 struct excl_rel_decl
435 int all_names_num;
436 int first_list_length;
437 char *names [1];
440 /* This describes unit relations: [final_]presence_set or
441 [final_]absence_set (see file rtl.def). */
442 struct unit_pattern_rel_decl
444 int final_p;
445 int names_num;
446 int patterns_num;
447 char **names;
448 char ***patterns;
451 /* This describes define_reservation (see file rtl.def). */
452 struct reserv_decl
454 const char *name;
455 regexp_t regexp;
457 /* The following fields are defined by checker. */
459 /* The following field value is nonzero if the unit is used in an
460 regexp. */
461 char reserv_is_used;
462 /* The following field is used to check up cycle in expression
463 definition. */
464 int loop_pass_num;
467 /* This describes define_insn_reservation (see file rtl.def). */
468 struct insn_reserv_decl
470 rtx condexp;
471 int default_latency;
472 regexp_t regexp;
473 const char *name;
475 /* The following fields are defined by checker. */
477 /* The following field value is order number (0, 1, ...) of given
478 insn. */
479 int insn_num;
480 /* The following field value is list of bypasses in which given insn
481 is output insn. Bypasses with the same input insn stay one after
482 another in the list in the same order as their occurrences in the
483 description but the bypass without a guard stays always the last
484 in a row of bypasses with the same input insn. */
485 struct bypass_decl *bypass_list;
487 /* The following fields are defined by automaton generator. */
489 /* The following field is the insn regexp transformed that
490 the regexp has not optional regexp, repetition regexp, and an
491 reservation name (i.e. reservation identifiers are changed by the
492 corresponding regexp) and all alternations are the top level
493 of the regexp. The value can be NULL only if it is special
494 insn `cycle advancing'. */
495 regexp_t transformed_regexp;
496 /* The following field value is list of arcs marked given
497 insn. The field is used in transformation NDFA -> DFA. */
498 arc_t arcs_marked_by_insn;
499 /* The two following fields are used during minimization of a finite state
500 automaton. */
501 /* The field value is number of equivalence class of state into
502 which arc marked by given insn enters from a state (fixed during
503 an automaton minimization). */
504 int equiv_class_num;
505 /* The following member value is the list to automata which can be
506 changed by the insn issue. */
507 automata_list_el_t important_automata_list;
508 /* The following member is used to process insn once for output. */
509 int processed_p;
512 /* This contains a declaration mentioned above. */
513 struct decl
515 /* What node in the union? */
516 enum decl_mode mode;
517 pos_t pos;
518 union
520 struct unit_decl unit;
521 struct bypass_decl bypass;
522 struct automaton_decl automaton;
523 struct excl_rel_decl excl;
524 struct unit_pattern_rel_decl presence;
525 struct unit_pattern_rel_decl absence;
526 struct reserv_decl reserv;
527 struct insn_reserv_decl insn_reserv;
528 } decl;
531 /* The following structures represent parsed reservation strings. */
532 enum regexp_mode
534 rm_unit,
535 rm_reserv,
536 rm_nothing,
537 rm_sequence,
538 rm_repeat,
539 rm_allof,
540 rm_oneof
543 /* Cpu unit in reservation. */
544 struct unit_regexp
546 const char *name;
547 unit_decl_t unit_decl;
550 /* Define_reservation in a reservation. */
551 struct reserv_regexp
553 const char *name;
554 struct reserv_decl *reserv_decl;
557 /* Absence of reservation (represented by string `nothing'). */
558 struct nothing_regexp
560 /* This used to be empty but ISO C doesn't allow that. */
561 char unused;
564 /* Representation of reservations separated by ',' (see file
565 rtl.def). */
566 struct sequence_regexp
568 int regexps_num;
569 regexp_t regexps [1];
572 /* Representation of construction `repeat' (see file rtl.def). */
573 struct repeat_regexp
575 int repeat_num;
576 regexp_t regexp;
579 /* Representation of reservations separated by '+' (see file
580 rtl.def). */
581 struct allof_regexp
583 int regexps_num;
584 regexp_t regexps [1];
587 /* Representation of reservations separated by '|' (see file
588 rtl.def). */
589 struct oneof_regexp
591 int regexps_num;
592 regexp_t regexps [1];
595 /* Representation of a reservation string. */
596 struct regexp
598 /* What node in the union? */
599 enum regexp_mode mode;
600 pos_t pos;
601 union
603 struct unit_regexp unit;
604 struct reserv_regexp reserv;
605 struct nothing_regexp nothing;
606 struct sequence_regexp sequence;
607 struct repeat_regexp repeat;
608 struct allof_regexp allof;
609 struct oneof_regexp oneof;
610 } regexp;
613 /* Represents description of pipeline hazard description based on
614 NDFA. */
615 struct description
617 int decls_num, normal_decls_num;
619 /* The following fields are defined by checker. */
621 /* The following fields values are correspondingly number of all
622 units, query units, and insns in the description. */
623 int units_num;
624 int query_units_num;
625 int insns_num;
626 /* The following field value is max length (in cycles) of
627 reservations of insns. The field value is defined only for
628 correct programs. */
629 int max_insn_reserv_cycles;
631 /* The following fields are defined by automaton generator. */
633 /* The following field value is the first automaton. */
634 automaton_t first_automaton;
636 /* The following field is created by pipeline hazard parser and
637 contains all declarations. We allocate additional entries for
638 two special insns which are added by the automaton generator. */
639 decl_t decls [1];
643 /* The following nodes are created in automaton checker. */
645 /* The following nodes represent exclusion set for cpu units. Each
646 element is accessed through only one excl_list. */
647 struct unit_set_el
649 unit_decl_t unit_decl;
650 unit_set_el_t next_unit_set_el;
653 /* The following nodes represent presence or absence pattern for cpu
654 units. Each element is accessed through only one presence_list or
655 absence_list. */
656 struct pattern_set_el
658 /* The number of units in unit_decls. */
659 int units_num;
660 /* The units forming the pattern. */
661 struct unit_decl **unit_decls;
662 pattern_set_el_t next_pattern_set_el;
666 /* The following nodes are created in automaton generator. */
669 /* The following nodes represent presence or absence pattern for cpu
670 units. Each element is accessed through only one element of
671 unit_presence_set_table or unit_absence_set_table. */
672 struct pattern_reserv
674 reserv_sets_t reserv;
675 pattern_reserv_t next_pattern_reserv;
678 /* The following node type describes state automaton. The state may
679 be deterministic or non-deterministic. Non-deterministic state has
680 several component states which represent alternative cpu units
681 reservations. The state also is used for describing a
682 deterministic reservation of automaton insn. */
683 struct state
685 /* The following member value is nonzero if there is a transition by
686 cycle advancing. */
687 int new_cycle_p;
688 /* The following field is list of processor unit reservations on
689 each cycle. */
690 reserv_sets_t reservs;
691 /* The following field is unique number of given state between other
692 states. */
693 int unique_num;
694 /* The following field value is automaton to which given state
695 belongs. */
696 automaton_t automaton;
697 /* The following field value is the first arc output from given
698 state. */
699 arc_t first_out_arc;
700 unsigned int num_out_arcs;
701 /* The following field is used to form NDFA. */
702 char it_was_placed_in_stack_for_NDFA_forming;
703 /* The following field is used to form DFA. */
704 char it_was_placed_in_stack_for_DFA_forming;
705 /* The following field is used to transform NDFA to DFA and DFA
706 minimization. The field value is not NULL if the state is a
707 compound state. In this case the value of field `unit_sets_list'
708 is NULL. All states in the list are in the hash table. The list
709 is formed through field `next_sorted_alt_state'. We should
710 support only one level of nesting state. */
711 alt_state_t component_states;
712 /* The following field is used for passing graph of states. */
713 int pass_num;
714 /* The list of states belonging to one equivalence class is formed
715 with the aid of the following field. */
716 state_t next_equiv_class_state;
717 /* The two following fields are used during minimization of a finite
718 state automaton. */
719 int equiv_class_num_1, equiv_class_num_2;
720 /* The following field is used during minimization of a finite state
721 automaton. The field value is state corresponding to equivalence
722 class to which given state belongs. */
723 state_t equiv_class_state;
724 unsigned int *presence_signature;
725 /* The following field value is the order number of given state.
726 The states in final DFA is enumerated with the aid of the
727 following field. */
728 int order_state_num;
729 /* This member is used for passing states for searching minimal
730 delay time. */
731 int state_pass_num;
732 /* The following member is used to evaluate min issue delay of insn
733 for a state. */
734 int min_insn_issue_delay;
737 /* Automaton arc. */
738 struct arc
740 /* The following field refers for the state into which given arc
741 enters. */
742 state_t to_state;
743 /* The following field describes that the insn issue (with cycle
744 advancing for special insn `cycle advancing' and without cycle
745 advancing for others) makes transition from given state to
746 another given state. */
747 ainsn_t insn;
748 /* The following field value is the next arc output from the same
749 state. */
750 arc_t next_out_arc;
751 /* List of arcs marked given insn is formed with the following
752 field. The field is used in transformation NDFA -> DFA. */
753 arc_t next_arc_marked_by_insn;
756 /* The following node type describes a deterministic alternative in
757 non-deterministic state which characterizes cpu unit reservations
758 of automaton insn or which is part of NDFA. */
759 struct alt_state
761 /* The following field is a deterministic state which characterizes
762 unit reservations of the instruction. */
763 state_t state;
764 /* The following field refers to the next state which characterizes
765 unit reservations of the instruction. */
766 alt_state_t next_alt_state;
767 /* The following field refers to the next state in sorted list. */
768 alt_state_t next_sorted_alt_state;
771 /* The following node type describes insn of automaton. They are
772 labels of FA arcs. */
773 struct ainsn
775 /* The following field value is the corresponding insn declaration
776 of description. */
777 struct insn_reserv_decl *insn_reserv_decl;
778 /* The following field value is the next insn declaration for an
779 automaton. */
780 ainsn_t next_ainsn;
781 /* The following field is states which characterize automaton unit
782 reservations of the instruction. The value can be NULL only if it
783 is special insn `cycle advancing'. */
784 alt_state_t alt_states;
785 /* The following field is sorted list of states which characterize
786 automaton unit reservations of the instruction. The value can be
787 NULL only if it is special insn `cycle advancing'. */
788 alt_state_t sorted_alt_states;
789 /* The following field refers the next automaton insn with
790 the same reservations. */
791 ainsn_t next_same_reservs_insn;
792 /* The following field is flag of the first automaton insn with the
793 same reservations in the declaration list. Only arcs marked such
794 insn is present in the automaton. This significantly decreases
795 memory requirements especially when several automata are
796 formed. */
797 char first_insn_with_same_reservs;
798 /* The following member has nonzero value if there is arc from state of
799 the automaton marked by the ainsn. */
800 char arc_exists_p;
801 /* Cyclic list of insns of an equivalence class is formed with the
802 aid of the following field. */
803 ainsn_t next_equiv_class_insn;
804 /* The following field value is nonzero if the insn declaration is
805 the first insn declaration with given equivalence number. */
806 char first_ainsn_with_given_equivalence_num;
807 /* The following field is number of class of equivalence of insns.
808 It is necessary because many insns may be equivalent with the
809 point of view of pipeline hazards. */
810 int insn_equiv_class_num;
811 /* The following member value is TRUE if there is an arc in the
812 automaton marked by the insn into another state. In other
813 words, the insn can change the state of the automaton. */
814 int important_p;
817 /* The following describes an automaton for PHR. */
818 struct automaton
820 /* The following field value is the list of insn declarations for
821 given automaton. */
822 ainsn_t ainsn_list;
823 /* Pointers to the ainsns corresponding to the special reservations. */
824 ainsn_t advance_ainsn, collapse_ainsn;
826 /* The following field value is the corresponding automaton
827 declaration. This field is not NULL only if the automatic
828 partition on automata is not used. */
829 struct automaton_decl *corresponding_automaton_decl;
830 /* The following field value is the next automaton. */
831 automaton_t next_automaton;
832 /* The following field is start state of FA. There are not unit
833 reservations in the state. */
834 state_t start_state;
835 /* The following field value is number of equivalence classes of
836 insns (see field `insn_equiv_class_num' in
837 `insn_reserv_decl'). */
838 int insn_equiv_classes_num;
839 /* The following field value is number of states of final DFA. */
840 int achieved_states_num;
841 /* The following field value is the order number (0, 1, ...) of
842 given automaton. */
843 int automaton_order_num;
844 /* The following fields contain statistics information about
845 building automaton. */
846 int NDFA_states_num, DFA_states_num;
847 /* The following field value is defined only if minimization of DFA
848 is used. */
849 int minimal_DFA_states_num;
850 int NDFA_arcs_num, DFA_arcs_num;
851 /* The following field value is defined only if minimization of DFA
852 is used. */
853 int minimal_DFA_arcs_num;
854 /* The following member refers for two table state x ainsn -> int.
855 ??? Above sentence is incomprehensible. */
856 state_ainsn_table_t trans_table;
857 /* The following member value is maximal value of min issue delay
858 for insns of the automaton. */
859 int max_min_delay;
860 /* Usually min issue delay is small and we can place several (2, 4,
861 8) elements in one vector element. So the compression factor can
862 be 1 (no compression), 2, 4, 8. */
863 int min_issue_delay_table_compression_factor;
864 /* Total number of locked states in this automaton. */
865 int locked_states;
868 /* The following is the element of the list of automata. */
869 struct automata_list_el
871 /* The automaton itself. */
872 automaton_t automaton;
873 /* The next automata set element. */
874 automata_list_el_t next_automata_list_el;
877 /* The following structure describes a table state X ainsn -> int(>= 0). */
878 struct state_ainsn_table
880 /* Automaton to which given table belongs. */
881 automaton_t automaton;
882 /* The following tree vectors for comb vector implementation of the
883 table. */
884 vla_hwint_t comb_vect;
885 vla_hwint_t check_vect;
886 vla_hwint_t base_vect;
887 /* This is simple implementation of the table. */
888 vla_hwint_t full_vect;
889 /* Minimal and maximal values of the previous vectors. */
890 int min_comb_vect_el_value, max_comb_vect_el_value;
891 int min_base_vect_el_value, max_base_vect_el_value;
894 /* Macros to access members of unions. Use only them for access to
895 union members of declarations and regexps. */
897 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
899 #define DECL_UNIT(d) __extension__ \
900 (({ __typeof (d) const _decl = (d); \
901 if (_decl->mode != dm_unit) \
902 decl_mode_check_failed (_decl->mode, "dm_unit", \
903 __FILE__, __LINE__, __FUNCTION__); \
904 &(_decl)->decl.unit; }))
906 #define DECL_BYPASS(d) __extension__ \
907 (({ __typeof (d) const _decl = (d); \
908 if (_decl->mode != dm_bypass) \
909 decl_mode_check_failed (_decl->mode, "dm_bypass", \
910 __FILE__, __LINE__, __FUNCTION__); \
911 &(_decl)->decl.bypass; }))
913 #define DECL_AUTOMATON(d) __extension__ \
914 (({ __typeof (d) const _decl = (d); \
915 if (_decl->mode != dm_automaton) \
916 decl_mode_check_failed (_decl->mode, "dm_automaton", \
917 __FILE__, __LINE__, __FUNCTION__); \
918 &(_decl)->decl.automaton; }))
920 #define DECL_EXCL(d) __extension__ \
921 (({ __typeof (d) const _decl = (d); \
922 if (_decl->mode != dm_excl) \
923 decl_mode_check_failed (_decl->mode, "dm_excl", \
924 __FILE__, __LINE__, __FUNCTION__); \
925 &(_decl)->decl.excl; }))
927 #define DECL_PRESENCE(d) __extension__ \
928 (({ __typeof (d) const _decl = (d); \
929 if (_decl->mode != dm_presence) \
930 decl_mode_check_failed (_decl->mode, "dm_presence", \
931 __FILE__, __LINE__, __FUNCTION__); \
932 &(_decl)->decl.presence; }))
934 #define DECL_ABSENCE(d) __extension__ \
935 (({ __typeof (d) const _decl = (d); \
936 if (_decl->mode != dm_absence) \
937 decl_mode_check_failed (_decl->mode, "dm_absence", \
938 __FILE__, __LINE__, __FUNCTION__); \
939 &(_decl)->decl.absence; }))
941 #define DECL_RESERV(d) __extension__ \
942 (({ __typeof (d) const _decl = (d); \
943 if (_decl->mode != dm_reserv) \
944 decl_mode_check_failed (_decl->mode, "dm_reserv", \
945 __FILE__, __LINE__, __FUNCTION__); \
946 &(_decl)->decl.reserv; }))
948 #define DECL_INSN_RESERV(d) __extension__ \
949 (({ __typeof (d) const _decl = (d); \
950 if (_decl->mode != dm_insn_reserv) \
951 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
952 __FILE__, __LINE__, __FUNCTION__); \
953 &(_decl)->decl.insn_reserv; }))
955 static const char *decl_name (enum decl_mode);
956 static void decl_mode_check_failed (enum decl_mode, const char *,
957 const char *, int, const char *)
958 ATTRIBUTE_NORETURN;
960 /* Return string representation of declaration mode MODE. */
961 static const char *
962 decl_name (enum decl_mode mode)
964 static char str [100];
966 if (mode == dm_unit)
967 return "dm_unit";
968 else if (mode == dm_bypass)
969 return "dm_bypass";
970 else if (mode == dm_automaton)
971 return "dm_automaton";
972 else if (mode == dm_excl)
973 return "dm_excl";
974 else if (mode == dm_presence)
975 return "dm_presence";
976 else if (mode == dm_absence)
977 return "dm_absence";
978 else if (mode == dm_reserv)
979 return "dm_reserv";
980 else if (mode == dm_insn_reserv)
981 return "dm_insn_reserv";
982 else
983 sprintf (str, "unknown (%d)", (int) mode);
984 return str;
987 /* The function prints message about unexpected declaration and finish
988 the program. */
989 static void
990 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
991 const char *file, int line, const char *func)
993 fprintf
994 (stderr,
995 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
996 file, line, func, expected_mode_str, decl_name (mode));
997 exit (1);
1001 #define REGEXP_UNIT(r) __extension__ \
1002 (({ struct regexp *const _regexp = (r); \
1003 if (_regexp->mode != rm_unit) \
1004 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
1005 __FILE__, __LINE__, __FUNCTION__); \
1006 &(_regexp)->regexp.unit; }))
1008 #define REGEXP_RESERV(r) __extension__ \
1009 (({ struct regexp *const _regexp = (r); \
1010 if (_regexp->mode != rm_reserv) \
1011 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
1012 __FILE__, __LINE__, __FUNCTION__); \
1013 &(_regexp)->regexp.reserv; }))
1015 #define REGEXP_SEQUENCE(r) __extension__ \
1016 (({ struct regexp *const _regexp = (r); \
1017 if (_regexp->mode != rm_sequence) \
1018 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
1019 __FILE__, __LINE__, __FUNCTION__); \
1020 &(_regexp)->regexp.sequence; }))
1022 #define REGEXP_REPEAT(r) __extension__ \
1023 (({ struct regexp *const _regexp = (r); \
1024 if (_regexp->mode != rm_repeat) \
1025 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1026 __FILE__, __LINE__, __FUNCTION__); \
1027 &(_regexp)->regexp.repeat; }))
1029 #define REGEXP_ALLOF(r) __extension__ \
1030 (({ struct regexp *const _regexp = (r); \
1031 if (_regexp->mode != rm_allof) \
1032 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1033 __FILE__, __LINE__, __FUNCTION__); \
1034 &(_regexp)->regexp.allof; }))
1036 #define REGEXP_ONEOF(r) __extension__ \
1037 (({ struct regexp *const _regexp = (r); \
1038 if (_regexp->mode != rm_oneof) \
1039 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1040 __FILE__, __LINE__, __FUNCTION__); \
1041 &(_regexp)->regexp.oneof; }))
1043 static const char *regexp_name (enum regexp_mode);
1044 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1045 const char *, int,
1046 const char *) ATTRIBUTE_NORETURN;
1049 /* Return string representation of regexp mode MODE. */
1050 static const char *
1051 regexp_name (enum regexp_mode mode)
1053 switch (mode)
1055 case rm_unit:
1056 return "rm_unit";
1057 case rm_reserv:
1058 return "rm_reserv";
1059 case rm_nothing:
1060 return "rm_nothing";
1061 case rm_sequence:
1062 return "rm_sequence";
1063 case rm_repeat:
1064 return "rm_repeat";
1065 case rm_allof:
1066 return "rm_allof";
1067 case rm_oneof:
1068 return "rm_oneof";
1069 default:
1070 gcc_unreachable ();
1074 /* The function prints message about unexpected regexp and finish the
1075 program. */
1076 static void
1077 regexp_mode_check_failed (enum regexp_mode mode,
1078 const char *expected_mode_str,
1079 const char *file, int line, const char *func)
1081 fprintf
1082 (stderr,
1083 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1084 file, line, func, expected_mode_str, regexp_name (mode));
1085 exit (1);
1088 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1090 #define DECL_UNIT(d) (&(d)->decl.unit)
1091 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1092 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1093 #define DECL_EXCL(d) (&(d)->decl.excl)
1094 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1095 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1096 #define DECL_RESERV(d) (&(d)->decl.reserv)
1097 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1099 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1100 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1101 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1102 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1103 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1104 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1106 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1108 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1109 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1110 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1112 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1113 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1114 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1116 /* Create IR structure (node). */
1117 static void *
1118 create_node (size_t size)
1120 void *result;
1122 obstack_blank (&irp, size);
1123 result = obstack_base (&irp);
1124 obstack_finish (&irp);
1125 /* Default values of members are NULL and zero. */
1126 memset (result, 0, size);
1127 return result;
1130 /* Copy IR structure (node). */
1131 static void *
1132 copy_node (const void *from, size_t size)
1134 void *const result = create_node (size);
1135 memcpy (result, from, size);
1136 return result;
1139 /* The function checks that NAME does not contain quotes (`"'). */
1140 static const char *
1141 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1143 const char *str;
1145 for (str = name; *str != '\0'; str++)
1146 if (*str == '\"')
1147 error ("Name `%s' contains quotes", name);
1148 return name;
1151 /* Pointers to all declarations during IR generation are stored in the
1152 following. */
1153 static VEC(decl_t, heap) *decls;
1155 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1156 string containing the next separated element, taking parentheses
1157 into account if PAR_FLAG has nonzero value. Advance the pointer to
1158 after the string scanned, or the end-of-string. Return NULL if at
1159 end of string. */
1160 static char *
1161 next_sep_el (const char **pstr, int sep, int par_flag)
1163 char *out_str;
1164 const char *p;
1165 int pars_num;
1166 int n_spaces;
1168 /* Remove leading whitespaces. */
1169 while (ISSPACE ((int) **pstr))
1170 (*pstr)++;
1172 if (**pstr == '\0')
1173 return NULL;
1175 n_spaces = 0;
1176 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1178 if (par_flag && *p == '(')
1179 pars_num++;
1180 else if (par_flag && *p == ')')
1181 pars_num--;
1182 else if (pars_num == 0 && *p == sep)
1183 break;
1184 if (pars_num == 0 && ISSPACE ((int) *p))
1185 n_spaces++;
1186 else
1188 for (; n_spaces != 0; n_spaces--)
1189 obstack_1grow (&irp, p [-n_spaces]);
1190 obstack_1grow (&irp, *p);
1193 obstack_1grow (&irp, '\0');
1194 out_str = obstack_base (&irp);
1195 obstack_finish (&irp);
1197 *pstr = p;
1198 if (**pstr == sep)
1199 (*pstr)++;
1201 return out_str;
1204 /* Given a string and a separator, return the number of separated
1205 elements in it, taking parentheses into account if PAR_FLAG has
1206 nonzero value. Return 0 for the null string, -1 if parentheses is
1207 not balanced. */
1208 static int
1209 n_sep_els (const char *s, int sep, int par_flag)
1211 int n;
1212 int pars_num;
1214 if (*s == '\0')
1215 return 0;
1217 for (pars_num = 0, n = 1; *s; s++)
1218 if (par_flag && *s == '(')
1219 pars_num++;
1220 else if (par_flag && *s == ')')
1221 pars_num--;
1222 else if (pars_num == 0 && *s == sep)
1223 n++;
1225 return (pars_num != 0 ? -1 : n);
1228 /* Given a string and a separator, return vector of strings which are
1229 elements in the string and number of elements through els_num.
1230 Take parentheses into account if PAREN_P has nonzero value. The
1231 function also inserts the end marker NULL at the end of vector.
1232 Return 0 for the null string, -1 if parentheses are not balanced. */
1233 static char **
1234 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1236 int i;
1237 char **vect;
1238 const char **pstr;
1239 char *trail;
1241 *els_num = n_sep_els (str, sep, paren_p);
1242 if (*els_num <= 0)
1243 return NULL;
1244 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1245 vect = (char **) obstack_base (&irp);
1246 obstack_finish (&irp);
1247 pstr = &str;
1248 for (i = 0; i < *els_num; i++)
1249 vect [i] = next_sep_el (pstr, sep, paren_p);
1250 trail = next_sep_el (pstr, sep, paren_p);
1251 gcc_assert (!trail);
1252 vect [i] = NULL;
1253 return vect;
1256 /* Process a DEFINE_CPU_UNIT.
1258 This gives information about a unit contained in CPU. We fill a
1259 struct unit_decl with information used later by `expand_automata'. */
1260 static void
1261 gen_cpu_unit (rtx def)
1263 decl_t decl;
1264 char **str_cpu_units;
1265 int vect_length;
1266 int i;
1268 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1269 if (str_cpu_units == NULL)
1270 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1271 for (i = 0; i < vect_length; i++)
1273 decl = XCREATENODE (struct decl);
1274 decl->mode = dm_unit;
1275 decl->pos = 0;
1276 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1277 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1278 DECL_UNIT (decl)->query_p = 0;
1279 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1280 DECL_UNIT (decl)->in_set_p = 0;
1281 VEC_safe_push (decl_t, heap, decls, decl);
1285 /* Process a DEFINE_QUERY_CPU_UNIT.
1287 This gives information about a unit contained in CPU. We fill a
1288 struct unit_decl with information used later by `expand_automata'. */
1289 static void
1290 gen_query_cpu_unit (rtx def)
1292 decl_t decl;
1293 char **str_cpu_units;
1294 int vect_length;
1295 int i;
1297 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1298 FALSE);
1299 if (str_cpu_units == NULL)
1300 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1301 for (i = 0; i < vect_length; i++)
1303 decl = XCREATENODE (struct decl);
1304 decl->mode = dm_unit;
1305 decl->pos = 0;
1306 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1307 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1308 DECL_UNIT (decl)->query_p = 1;
1309 VEC_safe_push (decl_t, heap, decls, decl);
1313 /* Process a DEFINE_BYPASS.
1315 This gives information about a unit contained in the CPU. We fill
1316 in a struct bypass_decl with information used later by
1317 `expand_automata'. */
1318 static void
1319 gen_bypass (rtx def)
1321 decl_t decl;
1322 char **out_patterns;
1323 int out_length;
1324 char **in_patterns;
1325 int in_length;
1326 int i, j;
1328 out_patterns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1329 if (out_patterns == NULL)
1330 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1331 in_patterns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1332 if (in_patterns == NULL)
1333 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1334 for (i = 0; i < out_length; i++)
1335 for (j = 0; j < in_length; j++)
1337 decl = XCREATENODE (struct decl);
1338 decl->mode = dm_bypass;
1339 decl->pos = 0;
1340 DECL_BYPASS (decl)->latency = XINT (def, 0);
1341 DECL_BYPASS (decl)->out_pattern = out_patterns[i];
1342 DECL_BYPASS (decl)->in_pattern = in_patterns[j];
1343 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1344 VEC_safe_push (decl_t, heap, decls, decl);
1348 /* Process an EXCLUSION_SET.
1350 This gives information about a cpu unit conflicts. We fill a
1351 struct excl_rel_decl (excl) with information used later by
1352 `expand_automata'. */
1353 static void
1354 gen_excl_set (rtx def)
1356 decl_t decl;
1357 char **first_str_cpu_units;
1358 char **second_str_cpu_units;
1359 int first_vect_length;
1360 int length;
1361 int i;
1363 first_str_cpu_units
1364 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1365 if (first_str_cpu_units == NULL)
1366 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1367 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1368 FALSE);
1369 if (second_str_cpu_units == NULL)
1370 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1371 length += first_vect_length;
1372 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1373 decl->mode = dm_excl;
1374 decl->pos = 0;
1375 DECL_EXCL (decl)->all_names_num = length;
1376 DECL_EXCL (decl)->first_list_length = first_vect_length;
1377 for (i = 0; i < length; i++)
1378 if (i < first_vect_length)
1379 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1380 else
1381 DECL_EXCL (decl)->names [i]
1382 = second_str_cpu_units [i - first_vect_length];
1383 VEC_safe_push (decl_t, heap, decls, decl);
1386 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1387 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1389 This gives information about a cpu unit reservation requirements.
1390 We fill a struct unit_pattern_rel_decl with information used later
1391 by `expand_automata'. */
1392 static void
1393 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1395 decl_t decl;
1396 char **str_cpu_units;
1397 char **str_pattern_lists;
1398 char ***str_patterns;
1399 int cpu_units_length;
1400 int length;
1401 int patterns_length;
1402 int i;
1404 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1405 FALSE);
1406 if (str_cpu_units == NULL)
1407 fatal ((presence_p
1408 ? (final_p
1409 ? "invalid first string `%s' in final_presence_set"
1410 : "invalid first string `%s' in presence_set")
1411 : (final_p
1412 ? "invalid first string `%s' in final_absence_set"
1413 : "invalid first string `%s' in absence_set")),
1414 XSTR (def, 0));
1415 str_pattern_lists = get_str_vect (XSTR (def, 1),
1416 &patterns_length, ',', FALSE);
1417 if (str_pattern_lists == NULL)
1418 fatal ((presence_p
1419 ? (final_p
1420 ? "invalid second string `%s' in final_presence_set"
1421 : "invalid second string `%s' in presence_set")
1422 : (final_p
1423 ? "invalid second string `%s' in final_absence_set"
1424 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1425 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1426 for (i = 0; i < patterns_length; i++)
1428 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1429 &length, ' ', FALSE);
1430 gcc_assert (str_patterns [i]);
1432 decl = XCREATENODE (struct decl);
1433 decl->pos = 0;
1434 if (presence_p)
1436 decl->mode = dm_presence;
1437 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1438 DECL_PRESENCE (decl)->names = str_cpu_units;
1439 DECL_PRESENCE (decl)->patterns = str_patterns;
1440 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1441 DECL_PRESENCE (decl)->final_p = final_p;
1443 else
1445 decl->mode = dm_absence;
1446 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1447 DECL_ABSENCE (decl)->names = str_cpu_units;
1448 DECL_ABSENCE (decl)->patterns = str_patterns;
1449 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1450 DECL_ABSENCE (decl)->final_p = final_p;
1452 VEC_safe_push (decl_t, heap, decls, decl);
1455 /* Process a PRESENCE_SET.
1457 This gives information about a cpu unit reservation requirements.
1458 We fill a struct unit_pattern_rel_decl (presence) with information
1459 used later by `expand_automata'. */
1460 static void
1461 gen_presence_set (rtx def)
1463 gen_presence_absence_set (def, TRUE, FALSE);
1466 /* Process a FINAL_PRESENCE_SET.
1468 This gives information about a cpu unit reservation requirements.
1469 We fill a struct unit_pattern_rel_decl (presence) with information
1470 used later by `expand_automata'. */
1471 static void
1472 gen_final_presence_set (rtx def)
1474 gen_presence_absence_set (def, TRUE, TRUE);
1477 /* Process an ABSENCE_SET.
1479 This gives information about a cpu unit reservation requirements.
1480 We fill a struct unit_pattern_rel_decl (absence) with information
1481 used later by `expand_automata'. */
1482 static void
1483 gen_absence_set (rtx def)
1485 gen_presence_absence_set (def, FALSE, FALSE);
1488 /* Process a FINAL_ABSENCE_SET.
1490 This gives information about a cpu unit reservation requirements.
1491 We fill a struct unit_pattern_rel_decl (absence) with information
1492 used later by `expand_automata'. */
1493 static void
1494 gen_final_absence_set (rtx def)
1496 gen_presence_absence_set (def, FALSE, TRUE);
1499 /* Process a DEFINE_AUTOMATON.
1501 This gives information about a finite state automaton used for
1502 recognizing pipeline hazards. We fill a struct automaton_decl
1503 with information used later by `expand_automata'. */
1504 static void
1505 gen_automaton (rtx def)
1507 decl_t decl;
1508 char **str_automata;
1509 int vect_length;
1510 int i;
1512 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1513 if (str_automata == NULL)
1514 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1515 for (i = 0; i < vect_length; i++)
1517 decl = XCREATENODE (struct decl);
1518 decl->mode = dm_automaton;
1519 decl->pos = 0;
1520 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1521 VEC_safe_push (decl_t, heap, decls, decl);
1525 /* Process an AUTOMATA_OPTION.
1527 This gives information how to generate finite state automaton used
1528 for recognizing pipeline hazards. */
1529 static void
1530 gen_automata_option (rtx def)
1532 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1533 no_minimization_flag = 1;
1534 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1535 time_flag = 1;
1536 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1537 stats_flag = 1;
1538 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1539 v_flag = 1;
1540 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1541 w_flag = 1;
1542 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1543 ndfa_flag = 1;
1544 else if (strcmp (XSTR (def, 0), COLLAPSE_OPTION + 1) == 0)
1545 collapse_flag = 1;
1546 else if (strcmp (XSTR (def, 0), NO_COMB_OPTION + 1) == 0)
1547 no_comb_flag = 1;
1548 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1549 progress_flag = 1;
1550 else
1551 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1554 /* Name in reservation to denote absence reservation. */
1555 #define NOTHING_NAME "nothing"
1557 /* The following string contains original reservation string being
1558 parsed. */
1559 static const char *reserv_str;
1561 /* Parse an element in STR. */
1562 static regexp_t
1563 gen_regexp_el (const char *str)
1565 regexp_t regexp;
1566 char *dstr;
1567 int len;
1569 if (*str == '(')
1571 len = strlen (str);
1572 if (str [len - 1] != ')')
1573 fatal ("garbage after ) in reservation `%s'", reserv_str);
1574 dstr = XALLOCAVAR (char, len - 1);
1575 memcpy (dstr, str + 1, len - 2);
1576 dstr [len-2] = '\0';
1577 regexp = gen_regexp_sequence (dstr);
1579 else if (strcmp (str, NOTHING_NAME) == 0)
1581 regexp = XCREATENODE (struct regexp);
1582 regexp->mode = rm_nothing;
1584 else
1586 regexp = XCREATENODE (struct regexp);
1587 regexp->mode = rm_unit;
1588 REGEXP_UNIT (regexp)->name = str;
1590 return regexp;
1593 /* Parse construction `repeat' in STR. */
1594 static regexp_t
1595 gen_regexp_repeat (const char *str)
1597 regexp_t regexp;
1598 regexp_t repeat;
1599 char **repeat_vect;
1600 int els_num;
1601 int i;
1603 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1604 if (repeat_vect == NULL)
1605 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1606 if (els_num > 1)
1608 regexp = gen_regexp_el (repeat_vect [0]);
1609 for (i = 1; i < els_num; i++)
1611 repeat = XCREATENODE (struct regexp);
1612 repeat->mode = rm_repeat;
1613 REGEXP_REPEAT (repeat)->regexp = regexp;
1614 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1615 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1616 fatal ("repetition `%s' <= 1 in reservation `%s'",
1617 str, reserv_str);
1618 regexp = repeat;
1620 return regexp;
1622 else
1623 return gen_regexp_el (repeat_vect[0]);
1626 /* Parse reservation STR which possibly contains separator '+'. */
1627 static regexp_t
1628 gen_regexp_allof (const char *str)
1630 regexp_t allof;
1631 char **allof_vect;
1632 int els_num;
1633 int i;
1635 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1636 if (allof_vect == NULL)
1637 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1638 if (els_num > 1)
1640 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1641 + sizeof (regexp_t) * (els_num - 1));
1642 allof->mode = rm_allof;
1643 REGEXP_ALLOF (allof)->regexps_num = els_num;
1644 for (i = 0; i < els_num; i++)
1645 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1646 return allof;
1648 else
1649 return gen_regexp_repeat (allof_vect[0]);
1652 /* Parse reservation STR which possibly contains separator '|'. */
1653 static regexp_t
1654 gen_regexp_oneof (const char *str)
1656 regexp_t oneof;
1657 char **oneof_vect;
1658 int els_num;
1659 int i;
1661 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1662 if (oneof_vect == NULL)
1663 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1664 if (els_num > 1)
1666 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1667 + sizeof (regexp_t) * (els_num - 1));
1668 oneof->mode = rm_oneof;
1669 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1670 for (i = 0; i < els_num; i++)
1671 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1672 return oneof;
1674 else
1675 return gen_regexp_allof (oneof_vect[0]);
1678 /* Parse reservation STR which possibly contains separator ','. */
1679 static regexp_t
1680 gen_regexp_sequence (const char *str)
1682 regexp_t sequence;
1683 char **sequence_vect;
1684 int els_num;
1685 int i;
1687 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1688 if (els_num > 1)
1690 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1691 + sizeof (regexp_t) * (els_num - 1));
1692 sequence->mode = rm_sequence;
1693 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1694 for (i = 0; i < els_num; i++)
1695 REGEXP_SEQUENCE (sequence)->regexps [i]
1696 = gen_regexp_oneof (sequence_vect [i]);
1697 return sequence;
1699 else
1700 return gen_regexp_oneof (sequence_vect[0]);
1703 /* Parse construction reservation STR. */
1704 static regexp_t
1705 gen_regexp (const char *str)
1707 reserv_str = str;
1708 return gen_regexp_sequence (str);
1711 /* Process a DEFINE_RESERVATION.
1713 This gives information about a reservation of cpu units. We fill
1714 in a struct reserv_decl with information used later by
1715 `expand_automata'. */
1716 static void
1717 gen_reserv (rtx def)
1719 decl_t decl;
1721 decl = XCREATENODE (struct decl);
1722 decl->mode = dm_reserv;
1723 decl->pos = 0;
1724 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1725 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1726 VEC_safe_push (decl_t, heap, decls, decl);
1729 /* Process a DEFINE_INSN_RESERVATION.
1731 This gives information about the reservation of cpu units by an
1732 insn. We fill a struct insn_reserv_decl with information used
1733 later by `expand_automata'. */
1734 static void
1735 gen_insn_reserv (rtx def)
1737 decl_t decl;
1739 decl = XCREATENODE (struct decl);
1740 decl->mode = dm_insn_reserv;
1741 decl->pos = 0;
1742 DECL_INSN_RESERV (decl)->name
1743 = check_name (XSTR (def, 0), decl->pos);
1744 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1745 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1746 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1747 VEC_safe_push (decl_t, heap, decls, decl);
1752 /* The function evaluates hash value (0..UINT_MAX) of string. */
1753 static unsigned
1754 string_hash (const char *string)
1756 unsigned result, i;
1758 for (result = i = 0;*string++ != '\0'; i++)
1759 result += ((unsigned char) *string << (i % CHAR_BIT));
1760 return result;
1765 /* This page contains abstract data `table of automaton declarations'.
1766 Elements of the table is nodes representing automaton declarations.
1767 Key of the table elements is name of given automaton. Remember
1768 that automaton names have own space. */
1770 /* The function evaluates hash value of an automaton declaration. The
1771 function is used by abstract data `hashtab'. The function returns
1772 hash value (0..UINT_MAX) of given automaton declaration. */
1773 static hashval_t
1774 automaton_decl_hash (const void *automaton_decl)
1776 const_decl_t const decl = (const_decl_t) automaton_decl;
1778 gcc_assert (decl->mode != dm_automaton
1779 || DECL_AUTOMATON (decl)->name);
1780 return string_hash (DECL_AUTOMATON (decl)->name);
1783 /* The function tests automaton declarations on equality of their
1784 keys. The function is used by abstract data `hashtab'. The
1785 function returns 1 if the declarations have the same key, 0
1786 otherwise. */
1787 static int
1788 automaton_decl_eq_p (const void* automaton_decl_1,
1789 const void* automaton_decl_2)
1791 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1792 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1794 gcc_assert (decl1->mode == dm_automaton
1795 && DECL_AUTOMATON (decl1)->name
1796 && decl2->mode == dm_automaton
1797 && DECL_AUTOMATON (decl2)->name);
1798 return strcmp (DECL_AUTOMATON (decl1)->name,
1799 DECL_AUTOMATON (decl2)->name) == 0;
1802 /* The automaton declaration table itself is represented by the
1803 following variable. */
1804 static htab_t automaton_decl_table;
1806 /* The function inserts automaton declaration into the table. The
1807 function does nothing if an automaton declaration with the same key
1808 exists already in the table. The function returns automaton
1809 declaration node in the table with the same key as given automaton
1810 declaration node. */
1811 static decl_t
1812 insert_automaton_decl (decl_t automaton_decl)
1814 void **entry_ptr;
1816 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, INSERT);
1817 if (*entry_ptr == NULL)
1818 *entry_ptr = (void *) automaton_decl;
1819 return (decl_t) *entry_ptr;
1822 /* The following variable value is node representing automaton
1823 declaration. The node used for searching automaton declaration
1824 with given name. */
1825 static struct decl work_automaton_decl;
1827 /* The function searches for automaton declaration in the table with
1828 the same key as node representing name of the automaton
1829 declaration. The function returns node found in the table, NULL if
1830 such node does not exist in the table. */
1831 static decl_t
1832 find_automaton_decl (const char *name)
1834 void *entry;
1836 work_automaton_decl.mode = dm_automaton;
1837 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1838 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1839 return (decl_t) entry;
1842 /* The function creates empty automaton declaration table and node
1843 representing automaton declaration and used for searching automaton
1844 declaration with given name. The function must be called only once
1845 before any work with the automaton declaration table. */
1846 static void
1847 initiate_automaton_decl_table (void)
1849 work_automaton_decl.mode = dm_automaton;
1850 automaton_decl_table = htab_create (10, automaton_decl_hash,
1851 automaton_decl_eq_p, (htab_del) 0);
1854 /* The function deletes the automaton declaration table. Only call of
1855 function `initiate_automaton_decl_table' is possible immediately
1856 after this function call. */
1857 static void
1858 finish_automaton_decl_table (void)
1860 htab_delete (automaton_decl_table);
1865 /* This page contains abstract data `table of insn declarations'.
1866 Elements of the table is nodes representing insn declarations. Key
1867 of the table elements is name of given insn (in corresponding
1868 define_insn_reservation). Remember that insn names have own
1869 space. */
1871 /* The function evaluates hash value of an insn declaration. The
1872 function is used by abstract data `hashtab'. The function returns
1873 hash value (0..UINT_MAX) of given insn declaration. */
1874 static hashval_t
1875 insn_decl_hash (const void *insn_decl)
1877 const_decl_t const decl = (const_decl_t) insn_decl;
1879 gcc_assert (decl->mode == dm_insn_reserv
1880 && DECL_INSN_RESERV (decl)->name);
1881 return string_hash (DECL_INSN_RESERV (decl)->name);
1884 /* The function tests insn declarations on equality of their keys.
1885 The function is used by abstract data `hashtab'. The function
1886 returns 1 if declarations have the same key, 0 otherwise. */
1887 static int
1888 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1890 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1891 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1893 gcc_assert (decl1->mode == dm_insn_reserv
1894 && DECL_INSN_RESERV (decl1)->name
1895 && decl2->mode == dm_insn_reserv
1896 && DECL_INSN_RESERV (decl2)->name);
1897 return strcmp (DECL_INSN_RESERV (decl1)->name,
1898 DECL_INSN_RESERV (decl2)->name) == 0;
1901 /* The insn declaration table itself is represented by the following
1902 variable. The table does not contain insn reservation
1903 declarations. */
1904 static htab_t insn_decl_table;
1906 /* The function inserts insn declaration into the table. The function
1907 does nothing if an insn declaration with the same key exists
1908 already in the table. The function returns insn declaration node
1909 in the table with the same key as given insn declaration node. */
1910 static decl_t
1911 insert_insn_decl (decl_t insn_decl)
1913 void **entry_ptr;
1915 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, INSERT);
1916 if (*entry_ptr == NULL)
1917 *entry_ptr = (void *) insn_decl;
1918 return (decl_t) *entry_ptr;
1921 /* The following variable value is node representing insn reservation
1922 declaration. The node used for searching insn reservation
1923 declaration with given name. */
1924 static struct decl work_insn_decl;
1926 /* The function searches for insn reservation declaration in the table
1927 with the same key as node representing name of the insn reservation
1928 declaration. The function returns node found in the table, NULL if
1929 such node does not exist in the table. */
1930 static decl_t
1931 find_insn_decl (const char *name)
1933 void *entry;
1935 work_insn_decl.mode = dm_insn_reserv;
1936 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1937 entry = htab_find (insn_decl_table, &work_insn_decl);
1938 return (decl_t) entry;
1941 /* The function creates empty insn declaration table and node
1942 representing insn declaration and used for searching insn
1943 declaration with given name. The function must be called only once
1944 before any work with the insn declaration table. */
1945 static void
1946 initiate_insn_decl_table (void)
1948 work_insn_decl.mode = dm_insn_reserv;
1949 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1950 (htab_del) 0);
1953 /* The function deletes the insn declaration table. Only call of
1954 function `initiate_insn_decl_table' is possible immediately after
1955 this function call. */
1956 static void
1957 finish_insn_decl_table (void)
1959 htab_delete (insn_decl_table);
1964 /* This page contains abstract data `table of declarations'. Elements
1965 of the table is nodes representing declarations (of units and
1966 reservations). Key of the table elements is names of given
1967 declarations. */
1969 /* The function evaluates hash value of a declaration. The function
1970 is used by abstract data `hashtab'. The function returns hash
1971 value (0..UINT_MAX) of given declaration. */
1972 static hashval_t
1973 decl_hash (const void *decl)
1975 const_decl_t const d = (const_decl_t) decl;
1977 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1978 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1979 return string_hash (d->mode == dm_unit
1980 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1983 /* The function tests declarations on equality of their keys. The
1984 function is used by abstract data 'hashtab'. The function
1985 returns 1 if the declarations have the same key, 0 otherwise. */
1986 static int
1987 decl_eq_p (const void *decl_1, const void *decl_2)
1989 const_decl_t const d1 = (const_decl_t) decl_1;
1990 const_decl_t const d2 = (const_decl_t) decl_2;
1992 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1993 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1994 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1995 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1996 return strcmp ((d1->mode == dm_unit
1997 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1998 (d2->mode == dm_unit
1999 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
2002 /* The declaration table itself is represented by the following
2003 variable. */
2004 static htab_t decl_table;
2006 /* The function inserts declaration into the table. The function does
2007 nothing if a declaration with the same key exists already in the
2008 table. The function returns declaration node in the table with the
2009 same key as given declaration node. */
2011 static decl_t
2012 insert_decl (decl_t decl)
2014 void **entry_ptr;
2016 entry_ptr = htab_find_slot (decl_table, decl, INSERT);
2017 if (*entry_ptr == NULL)
2018 *entry_ptr = (void *) decl;
2019 return (decl_t) *entry_ptr;
2022 /* The following variable value is node representing declaration. The
2023 node used for searching declaration with given name. */
2024 static struct decl work_decl;
2026 /* The function searches for declaration in the table with the same
2027 key as node representing name of the declaration. The function
2028 returns node found in the table, NULL if such node does not exist
2029 in the table. */
2030 static decl_t
2031 find_decl (const char *name)
2033 void *entry;
2035 work_decl.mode = dm_unit;
2036 DECL_UNIT (&work_decl)->name = name;
2037 entry = htab_find (decl_table, &work_decl);
2038 return (decl_t) entry;
2041 /* The function creates empty declaration table and node representing
2042 declaration and used for searching declaration with given name.
2043 The function must be called only once before any work with the
2044 declaration table. */
2045 static void
2046 initiate_decl_table (void)
2048 work_decl.mode = dm_unit;
2049 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2052 /* The function deletes the declaration table. Only call of function
2053 `initiate_declaration_table' is possible immediately after this
2054 function call. */
2055 static void
2056 finish_decl_table (void)
2058 htab_delete (decl_table);
2063 /* This page contains checker of pipeline hazard description. */
2065 /* Checking NAMES in an exclusion clause vector and returning formed
2066 unit_set_el_list. */
2067 static unit_set_el_t
2068 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2070 unit_set_el_t el_list;
2071 unit_set_el_t last_el;
2072 unit_set_el_t new_el;
2073 decl_t decl_in_table;
2074 int i;
2076 el_list = NULL;
2077 last_el = NULL;
2078 for (i = 0; i < num; i++)
2080 decl_in_table = find_decl (names [i]);
2081 if (decl_in_table == NULL)
2082 error ("unit `%s' in exclusion is not declared", names [i]);
2083 else if (decl_in_table->mode != dm_unit)
2084 error ("`%s' in exclusion is not unit", names [i]);
2085 else
2087 new_el = XCREATENODE (struct unit_set_el);
2088 new_el->unit_decl = DECL_UNIT (decl_in_table);
2089 new_el->next_unit_set_el = NULL;
2090 if (last_el == NULL)
2091 el_list = last_el = new_el;
2092 else
2094 last_el->next_unit_set_el = new_el;
2095 last_el = last_el->next_unit_set_el;
2099 return el_list;
2102 /* The function adds each element from SOURCE_LIST to the exclusion
2103 list of the each element from DEST_LIST. Checking situation "unit
2104 excludes itself". */
2105 static void
2106 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2107 pos_t excl_pos ATTRIBUTE_UNUSED)
2109 unit_set_el_t dst;
2110 unit_set_el_t src;
2111 unit_set_el_t curr_el;
2112 unit_set_el_t prev_el;
2113 unit_set_el_t copy;
2115 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2116 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2118 if (dst->unit_decl == src->unit_decl)
2120 error ("unit `%s' excludes itself", src->unit_decl->name);
2121 continue;
2123 if (dst->unit_decl->automaton_name != NULL
2124 && src->unit_decl->automaton_name != NULL
2125 && strcmp (dst->unit_decl->automaton_name,
2126 src->unit_decl->automaton_name) != 0)
2128 error ("units `%s' and `%s' in exclusion set belong to different automata",
2129 src->unit_decl->name, dst->unit_decl->name);
2130 continue;
2132 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2133 curr_el != NULL;
2134 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2135 if (curr_el->unit_decl == src->unit_decl)
2136 break;
2137 if (curr_el == NULL)
2139 /* Element not found - insert. */
2140 copy = XCOPYNODE (struct unit_set_el, src);
2141 copy->next_unit_set_el = NULL;
2142 if (prev_el == NULL)
2143 dst->unit_decl->excl_list = copy;
2144 else
2145 prev_el->next_unit_set_el = copy;
2150 /* Checking NAMES in presence/absence clause and returning the
2151 formed unit_set_el_list. The function is called only after
2152 processing all exclusion sets. */
2153 static unit_set_el_t
2154 process_presence_absence_names (char **names, int num,
2155 pos_t req_pos ATTRIBUTE_UNUSED,
2156 int presence_p, int final_p)
2158 unit_set_el_t el_list;
2159 unit_set_el_t last_el;
2160 unit_set_el_t new_el;
2161 decl_t decl_in_table;
2162 int i;
2164 el_list = NULL;
2165 last_el = NULL;
2166 for (i = 0; i < num; i++)
2168 decl_in_table = find_decl (names [i]);
2169 if (decl_in_table == NULL)
2170 error ((presence_p
2171 ? (final_p
2172 ? "unit `%s' in final presence set is not declared"
2173 : "unit `%s' in presence set is not declared")
2174 : (final_p
2175 ? "unit `%s' in final absence set is not declared"
2176 : "unit `%s' in absence set is not declared")), names [i]);
2177 else if (decl_in_table->mode != dm_unit)
2178 error ((presence_p
2179 ? (final_p
2180 ? "`%s' in final presence set is not unit"
2181 : "`%s' in presence set is not unit")
2182 : (final_p
2183 ? "`%s' in final absence set is not unit"
2184 : "`%s' in absence set is not unit")), names [i]);
2185 else
2187 new_el = XCREATENODE (struct unit_set_el);
2188 new_el->unit_decl = DECL_UNIT (decl_in_table);
2189 new_el->next_unit_set_el = NULL;
2190 if (last_el == NULL)
2191 el_list = last_el = new_el;
2192 else
2194 last_el->next_unit_set_el = new_el;
2195 last_el = last_el->next_unit_set_el;
2199 return el_list;
2202 /* Checking NAMES in patterns of a presence/absence clause and
2203 returning the formed pattern_set_el_list. The function is called
2204 only after processing all exclusion sets. */
2205 static pattern_set_el_t
2206 process_presence_absence_patterns (char ***patterns, int num,
2207 pos_t req_pos ATTRIBUTE_UNUSED,
2208 int presence_p, int final_p)
2210 pattern_set_el_t el_list;
2211 pattern_set_el_t last_el;
2212 pattern_set_el_t new_el;
2213 decl_t decl_in_table;
2214 int i, j;
2216 el_list = NULL;
2217 last_el = NULL;
2218 for (i = 0; i < num; i++)
2220 for (j = 0; patterns [i] [j] != NULL; j++)
2222 new_el = XCREATENODEVAR (struct pattern_set_el,
2223 sizeof (struct pattern_set_el)
2224 + sizeof (struct unit_decl *) * j);
2225 new_el->unit_decls
2226 = (struct unit_decl **) ((char *) new_el
2227 + sizeof (struct pattern_set_el));
2228 new_el->next_pattern_set_el = NULL;
2229 if (last_el == NULL)
2230 el_list = last_el = new_el;
2231 else
2233 last_el->next_pattern_set_el = new_el;
2234 last_el = last_el->next_pattern_set_el;
2236 new_el->units_num = 0;
2237 for (j = 0; patterns [i] [j] != NULL; j++)
2239 decl_in_table = find_decl (patterns [i] [j]);
2240 if (decl_in_table == NULL)
2241 error ((presence_p
2242 ? (final_p
2243 ? "unit `%s' in final presence set is not declared"
2244 : "unit `%s' in presence set is not declared")
2245 : (final_p
2246 ? "unit `%s' in final absence set is not declared"
2247 : "unit `%s' in absence set is not declared")),
2248 patterns [i] [j]);
2249 else if (decl_in_table->mode != dm_unit)
2250 error ((presence_p
2251 ? (final_p
2252 ? "`%s' in final presence set is not unit"
2253 : "`%s' in presence set is not unit")
2254 : (final_p
2255 ? "`%s' in final absence set is not unit"
2256 : "`%s' in absence set is not unit")),
2257 patterns [i] [j]);
2258 else
2260 new_el->unit_decls [new_el->units_num]
2261 = DECL_UNIT (decl_in_table);
2262 new_el->units_num++;
2266 return el_list;
2269 /* The function adds each element from PATTERN_LIST to presence (if
2270 PRESENCE_P) or absence list of the each element from DEST_LIST.
2271 Checking situations "unit requires own absence", and "unit excludes
2272 and requires presence of ...", "unit requires absence and presence
2273 of ...", "units in (final) presence set belong to different
2274 automata", and "units in (final) absence set belong to different
2275 automata". Remember that we process absence sets only after all
2276 presence sets. */
2277 static void
2278 add_presence_absence (unit_set_el_t dest_list,
2279 pattern_set_el_t pattern_list,
2280 pos_t req_pos ATTRIBUTE_UNUSED,
2281 int presence_p, int final_p)
2283 unit_set_el_t dst;
2284 pattern_set_el_t pat;
2285 struct unit_decl *unit;
2286 unit_set_el_t curr_excl_el;
2287 pattern_set_el_t curr_pat_el;
2288 pattern_set_el_t prev_el;
2289 pattern_set_el_t copy;
2290 int i;
2291 int no_error_flag;
2293 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2294 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2296 for (i = 0; i < pat->units_num; i++)
2298 unit = pat->unit_decls [i];
2299 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2301 error ("unit `%s' requires own absence", unit->name);
2302 continue;
2304 if (dst->unit_decl->automaton_name != NULL
2305 && unit->automaton_name != NULL
2306 && strcmp (dst->unit_decl->automaton_name,
2307 unit->automaton_name) != 0)
2309 error ((presence_p
2310 ? (final_p
2311 ? "units `%s' and `%s' in final presence set belong to different automata"
2312 : "units `%s' and `%s' in presence set belong to different automata")
2313 : (final_p
2314 ? "units `%s' and `%s' in final absence set belong to different automata"
2315 : "units `%s' and `%s' in absence set belong to different automata")),
2316 unit->name, dst->unit_decl->name);
2317 continue;
2319 no_error_flag = 1;
2320 if (presence_p)
2321 for (curr_excl_el = dst->unit_decl->excl_list;
2322 curr_excl_el != NULL;
2323 curr_excl_el = curr_excl_el->next_unit_set_el)
2325 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2327 if (!w_flag)
2329 error ("unit `%s' excludes and requires presence of `%s'",
2330 dst->unit_decl->name, unit->name);
2331 no_error_flag = 0;
2333 else
2334 warning ("unit `%s' excludes and requires presence of `%s'",
2335 dst->unit_decl->name, unit->name);
2338 else if (pat->units_num == 1)
2339 for (curr_pat_el = dst->unit_decl->presence_list;
2340 curr_pat_el != NULL;
2341 curr_pat_el = curr_pat_el->next_pattern_set_el)
2342 if (curr_pat_el->units_num == 1
2343 && unit == curr_pat_el->unit_decls [0])
2345 if (!w_flag)
2347 error ("unit `%s' requires absence and presence of `%s'",
2348 dst->unit_decl->name, unit->name);
2349 no_error_flag = 0;
2351 else
2352 warning ("unit `%s' requires absence and presence of `%s'",
2353 dst->unit_decl->name, unit->name);
2355 if (no_error_flag)
2357 for (prev_el = (presence_p
2358 ? (final_p
2359 ? dst->unit_decl->final_presence_list
2360 : dst->unit_decl->final_presence_list)
2361 : (final_p
2362 ? dst->unit_decl->final_absence_list
2363 : dst->unit_decl->absence_list));
2364 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2365 prev_el = prev_el->next_pattern_set_el)
2367 copy = XCOPYNODE (struct pattern_set_el, pat);
2368 copy->next_pattern_set_el = NULL;
2369 if (prev_el == NULL)
2371 if (presence_p)
2373 if (final_p)
2374 dst->unit_decl->final_presence_list = copy;
2375 else
2376 dst->unit_decl->presence_list = copy;
2378 else if (final_p)
2379 dst->unit_decl->final_absence_list = copy;
2380 else
2381 dst->unit_decl->absence_list = copy;
2383 else
2384 prev_el->next_pattern_set_el = copy;
2391 /* The function inserts BYPASS in the list of bypasses of the
2392 corresponding output insn. The order of bypasses in the list is
2393 described in a comment for member `bypass_list' (see above). If
2394 there is already the same bypass in the list the function reports
2395 this and does nothing. */
2396 static void
2397 insert_bypass (struct bypass_decl *bypass)
2399 struct bypass_decl *curr, *last;
2400 struct insn_reserv_decl *out_insn_reserv = bypass->out_insn_reserv;
2401 struct insn_reserv_decl *in_insn_reserv = bypass->in_insn_reserv;
2403 for (curr = out_insn_reserv->bypass_list, last = NULL;
2404 curr != NULL;
2405 last = curr, curr = curr->next)
2406 if (curr->in_insn_reserv == in_insn_reserv)
2408 if ((bypass->bypass_guard_name != NULL
2409 && curr->bypass_guard_name != NULL
2410 && ! strcmp (bypass->bypass_guard_name, curr->bypass_guard_name))
2411 || bypass->bypass_guard_name == curr->bypass_guard_name)
2413 if (bypass->bypass_guard_name == NULL)
2415 if (!w_flag)
2416 error ("the same bypass `%s - %s' is already defined",
2417 bypass->out_pattern, bypass->in_pattern);
2418 else
2419 warning ("the same bypass `%s - %s' is already defined",
2420 bypass->out_pattern, bypass->in_pattern);
2422 else if (!w_flag)
2423 error ("the same bypass `%s - %s' (guard %s) is already defined",
2424 bypass->out_pattern, bypass->in_pattern,
2425 bypass->bypass_guard_name);
2426 else
2427 warning
2428 ("the same bypass `%s - %s' (guard %s) is already defined",
2429 bypass->out_pattern, bypass->in_pattern,
2430 bypass->bypass_guard_name);
2431 return;
2433 if (curr->bypass_guard_name == NULL)
2434 break;
2435 if (curr->next == NULL || curr->next->in_insn_reserv != in_insn_reserv)
2437 last = curr;
2438 break;
2442 if (last == NULL)
2444 bypass->next = out_insn_reserv->bypass_list;
2445 out_insn_reserv->bypass_list = bypass;
2447 else
2449 bypass->next = last->next;
2450 last->next = bypass;
2454 /* BYPASS is a define_bypass decl that includes glob pattern PATTERN.
2455 Call FN (BYPASS, INSN, DATA) for each matching instruction INSN. */
2457 static void
2458 for_each_matching_insn (decl_t bypass, const char *pattern,
2459 void (*fn) (decl_t, decl_t, void *), void *data)
2461 decl_t insn_reserv;
2462 bool matched_p;
2463 int i;
2465 matched_p = false;
2466 if (strpbrk (pattern, "*?["))
2467 for (i = 0; i < description->decls_num; i++)
2469 insn_reserv = description->decls[i];
2470 if (insn_reserv->mode == dm_insn_reserv
2471 && fnmatch (pattern, DECL_INSN_RESERV (insn_reserv)->name, 0) == 0)
2473 fn (bypass, insn_reserv, data);
2474 matched_p = true;
2477 else
2479 insn_reserv = find_insn_decl (pattern);
2480 if (insn_reserv)
2482 fn (bypass, insn_reserv, data);
2483 matched_p = true;
2486 if (!matched_p)
2487 error ("there is no insn reservation that matches `%s'", pattern);
2490 /* A subroutine of process_bypass that is called for each pair
2491 of matching instructions. OUT_INSN_RESERV is the output
2492 instruction and DATA is the input instruction. */
2494 static void
2495 process_bypass_2 (decl_t model, decl_t out_insn_reserv, void *data)
2497 struct bypass_decl *bypass;
2498 decl_t in_insn_reserv;
2500 in_insn_reserv = (decl_t) data;
2501 if (strcmp (DECL_INSN_RESERV (in_insn_reserv)->name,
2502 DECL_BYPASS (model)->in_pattern) == 0
2503 && strcmp (DECL_INSN_RESERV (out_insn_reserv)->name,
2504 DECL_BYPASS (model)->out_pattern) == 0)
2505 bypass = DECL_BYPASS (model);
2506 else
2508 bypass = XCNEW (struct bypass_decl);
2509 bypass->latency = DECL_BYPASS (model)->latency;
2510 bypass->out_pattern = DECL_INSN_RESERV (out_insn_reserv)->name;
2511 bypass->in_pattern = DECL_INSN_RESERV (in_insn_reserv)->name;
2512 bypass->bypass_guard_name = DECL_BYPASS (model)->bypass_guard_name;
2514 bypass->out_insn_reserv = DECL_INSN_RESERV (out_insn_reserv);
2515 bypass->in_insn_reserv = DECL_INSN_RESERV (in_insn_reserv);
2516 insert_bypass (bypass);
2519 /* A subroutine of process_bypass that is called for each input
2520 instruction IN_INSN_RESERV. */
2522 static void
2523 process_bypass_1 (decl_t bypass, decl_t in_insn_reserv,
2524 void *data ATTRIBUTE_UNUSED)
2526 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->out_pattern,
2527 process_bypass_2, in_insn_reserv);
2530 /* Process define_bypass decl BYPASS, inserting a bypass for each specific
2531 pair of insn reservations. */
2533 static void
2534 process_bypass (decl_t bypass)
2536 for_each_matching_insn (bypass, DECL_BYPASS (bypass)->in_pattern,
2537 process_bypass_1, NULL);
2540 /* The function processes pipeline description declarations, checks
2541 their correctness, and forms exclusion/presence/absence sets. */
2542 static void
2543 process_decls (void)
2545 decl_t decl;
2546 decl_t automaton_decl;
2547 decl_t decl_in_table;
2548 int automaton_presence;
2549 int i;
2551 /* Checking repeated automata declarations. */
2552 automaton_presence = 0;
2553 for (i = 0; i < description->decls_num; i++)
2555 decl = description->decls [i];
2556 if (decl->mode == dm_automaton)
2558 automaton_presence = 1;
2559 decl_in_table = insert_automaton_decl (decl);
2560 if (decl_in_table != decl)
2562 if (!w_flag)
2563 error ("repeated declaration of automaton `%s'",
2564 DECL_AUTOMATON (decl)->name);
2565 else
2566 warning ("repeated declaration of automaton `%s'",
2567 DECL_AUTOMATON (decl)->name);
2571 /* Checking undeclared automata, repeated declarations (except for
2572 automata) and correctness of their attributes (insn latency times
2573 etc.). */
2574 for (i = 0; i < description->decls_num; i++)
2576 decl = description->decls [i];
2577 if (decl->mode == dm_insn_reserv)
2579 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2580 error ("define_insn_reservation `%s' has negative latency time",
2581 DECL_INSN_RESERV (decl)->name);
2582 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2583 description->insns_num++;
2584 decl_in_table = insert_insn_decl (decl);
2585 if (decl_in_table != decl)
2586 error ("`%s' is already used as insn reservation name",
2587 DECL_INSN_RESERV (decl)->name);
2589 else if (decl->mode == dm_bypass)
2591 if (DECL_BYPASS (decl)->latency < 0)
2592 error ("define_bypass `%s - %s' has negative latency time",
2593 DECL_BYPASS (decl)->out_pattern,
2594 DECL_BYPASS (decl)->in_pattern);
2596 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2598 if (decl->mode == dm_unit)
2600 DECL_UNIT (decl)->automaton_decl = NULL;
2601 if (DECL_UNIT (decl)->automaton_name != NULL)
2603 automaton_decl
2604 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2605 if (automaton_decl == NULL)
2606 error ("automaton `%s' is not declared",
2607 DECL_UNIT (decl)->automaton_name);
2608 else
2610 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2611 DECL_UNIT (decl)->automaton_decl
2612 = DECL_AUTOMATON (automaton_decl);
2615 else if (automaton_presence)
2616 error ("define_unit `%s' without automaton when one defined",
2617 DECL_UNIT (decl)->name);
2618 DECL_UNIT (decl)->unit_num = description->units_num;
2619 description->units_num++;
2620 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2622 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2623 continue;
2625 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2627 else
2629 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2631 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2632 continue;
2634 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2636 if (decl_in_table == NULL)
2637 decl_in_table = insert_decl (decl);
2638 else
2640 if (decl->mode == dm_unit)
2641 error ("repeated declaration of unit `%s'",
2642 DECL_UNIT (decl)->name);
2643 else
2644 error ("repeated declaration of reservation `%s'",
2645 DECL_RESERV (decl)->name);
2649 /* Check bypasses and form list of bypasses for each (output)
2650 insn. */
2651 for (i = 0; i < description->decls_num; i++)
2653 decl = description->decls [i];
2654 if (decl->mode == dm_bypass)
2655 process_bypass (decl);
2658 /* Check exclusion set declarations and form exclusion sets. */
2659 for (i = 0; i < description->decls_num; i++)
2661 decl = description->decls [i];
2662 if (decl->mode == dm_excl)
2664 unit_set_el_t unit_set_el_list;
2665 unit_set_el_t unit_set_el_list_2;
2667 unit_set_el_list
2668 = process_excls (DECL_EXCL (decl)->names,
2669 DECL_EXCL (decl)->first_list_length, decl->pos);
2670 unit_set_el_list_2
2671 = process_excls (&DECL_EXCL (decl)->names
2672 [DECL_EXCL (decl)->first_list_length],
2673 DECL_EXCL (decl)->all_names_num
2674 - DECL_EXCL (decl)->first_list_length,
2675 decl->pos);
2676 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2677 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2681 /* Check presence set declarations and form presence sets. */
2682 for (i = 0; i < description->decls_num; i++)
2684 decl = description->decls [i];
2685 if (decl->mode == dm_presence)
2687 unit_set_el_t unit_set_el_list;
2688 pattern_set_el_t pattern_set_el_list;
2690 unit_set_el_list
2691 = process_presence_absence_names
2692 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2693 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2694 pattern_set_el_list
2695 = process_presence_absence_patterns
2696 (DECL_PRESENCE (decl)->patterns,
2697 DECL_PRESENCE (decl)->patterns_num,
2698 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2699 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2700 decl->pos, TRUE,
2701 DECL_PRESENCE (decl)->final_p);
2705 /* Check absence set declarations and form absence sets. */
2706 for (i = 0; i < description->decls_num; i++)
2708 decl = description->decls [i];
2709 if (decl->mode == dm_absence)
2711 unit_set_el_t unit_set_el_list;
2712 pattern_set_el_t pattern_set_el_list;
2714 unit_set_el_list
2715 = process_presence_absence_names
2716 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2717 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2718 pattern_set_el_list
2719 = process_presence_absence_patterns
2720 (DECL_ABSENCE (decl)->patterns,
2721 DECL_ABSENCE (decl)->patterns_num,
2722 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2723 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2724 decl->pos, FALSE,
2725 DECL_ABSENCE (decl)->final_p);
2730 /* The following function checks that declared automaton is used. If
2731 the automaton is not used, the function fixes error/warning. The
2732 following function must be called only after `process_decls'. */
2733 static void
2734 check_automaton_usage (void)
2736 decl_t decl;
2737 int i;
2739 for (i = 0; i < description->decls_num; i++)
2741 decl = description->decls [i];
2742 if (decl->mode == dm_automaton
2743 && !DECL_AUTOMATON (decl)->automaton_is_used)
2745 if (!w_flag)
2746 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2747 else
2748 warning ("automaton `%s' is not used",
2749 DECL_AUTOMATON (decl)->name);
2754 /* The following recursive function processes all regexp in order to
2755 fix usage of units or reservations and to fix errors of undeclared
2756 name. The function may change unit_regexp onto reserv_regexp.
2757 Remember that reserv_regexp does not exist before the function
2758 call. */
2759 static regexp_t
2760 process_regexp (regexp_t regexp)
2762 decl_t decl_in_table;
2763 regexp_t new_regexp;
2764 int i;
2766 switch (regexp->mode)
2768 case rm_unit:
2769 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2770 if (decl_in_table == NULL)
2771 error ("undeclared unit or reservation `%s'",
2772 REGEXP_UNIT (regexp)->name);
2773 else
2774 switch (decl_in_table->mode)
2776 case dm_unit:
2777 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2778 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2779 break;
2781 case dm_reserv:
2782 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2783 new_regexp = XCREATENODE (struct regexp);
2784 new_regexp->mode = rm_reserv;
2785 new_regexp->pos = regexp->pos;
2786 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2787 REGEXP_RESERV (new_regexp)->reserv_decl
2788 = DECL_RESERV (decl_in_table);
2789 regexp = new_regexp;
2790 break;
2792 default:
2793 gcc_unreachable ();
2795 break;
2796 case rm_sequence:
2797 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2798 REGEXP_SEQUENCE (regexp)->regexps [i]
2799 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2800 break;
2801 case rm_allof:
2802 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2803 REGEXP_ALLOF (regexp)->regexps [i]
2804 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2805 break;
2806 case rm_oneof:
2807 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2808 REGEXP_ONEOF (regexp)->regexps [i]
2809 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2810 break;
2811 case rm_repeat:
2812 REGEXP_REPEAT (regexp)->regexp
2813 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2814 break;
2815 case rm_nothing:
2816 break;
2817 default:
2818 gcc_unreachable ();
2820 return regexp;
2823 /* The following function processes regexp of define_reservation and
2824 define_insn_reservation with the aid of function
2825 `process_regexp'. */
2826 static void
2827 process_regexp_decls (void)
2829 decl_t decl;
2830 int i;
2832 for (i = 0; i < description->decls_num; i++)
2834 decl = description->decls [i];
2835 if (decl->mode == dm_reserv)
2836 DECL_RESERV (decl)->regexp
2837 = process_regexp (DECL_RESERV (decl)->regexp);
2838 else if (decl->mode == dm_insn_reserv)
2839 DECL_INSN_RESERV (decl)->regexp
2840 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2844 /* The following function checks that declared unit is used. If the
2845 unit is not used, the function fixes errors/warnings. The
2846 following function must be called only after `process_decls',
2847 `process_regexp_decls'. */
2848 static void
2849 check_usage (void)
2851 decl_t decl;
2852 int i;
2854 for (i = 0; i < description->decls_num; i++)
2856 decl = description->decls [i];
2857 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2859 if (!w_flag)
2860 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2861 else
2862 warning ("unit `%s' is not used", DECL_UNIT (decl)->name);
2864 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2866 if (!w_flag)
2867 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2868 else
2869 warning ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2874 /* The following variable value is number of reservation being
2875 processed on loop recognition. */
2876 static int curr_loop_pass_num;
2878 /* The following recursive function returns nonzero value if REGEXP
2879 contains given decl or reservations in given regexp refers for
2880 given decl. */
2881 static int
2882 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2884 int i;
2886 if (regexp == NULL)
2887 return 0;
2888 switch (regexp->mode)
2890 case rm_unit:
2891 return 0;
2893 case rm_reserv:
2894 if (start_decl->mode == dm_reserv
2895 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2896 return 1;
2897 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2898 == curr_loop_pass_num)
2899 /* declaration has been processed. */
2900 return 0;
2901 else
2903 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2904 = curr_loop_pass_num;
2905 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2906 start_decl);
2909 case rm_sequence:
2910 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2911 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2912 return 1;
2913 return 0;
2915 case rm_allof:
2916 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2917 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2918 return 1;
2919 return 0;
2921 case rm_oneof:
2922 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2923 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2924 return 1;
2925 return 0;
2927 case rm_repeat:
2928 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2930 case rm_nothing:
2931 return 0;
2933 default:
2934 gcc_unreachable ();
2938 /* The following function fixes errors "cycle in definition ...". The
2939 function uses function `loop_in_regexp' for that. */
2940 static void
2941 check_loops_in_regexps (void)
2943 decl_t decl;
2944 int i;
2946 for (i = 0; i < description->decls_num; i++)
2948 decl = description->decls [i];
2949 if (decl->mode == dm_reserv)
2950 DECL_RESERV (decl)->loop_pass_num = 0;
2952 for (i = 0; i < description->decls_num; i++)
2954 decl = description->decls [i];
2955 curr_loop_pass_num = i;
2957 if (decl->mode == dm_reserv)
2959 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2960 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2962 gcc_assert (DECL_RESERV (decl)->regexp);
2963 error ("cycle in definition of reservation `%s'",
2964 DECL_RESERV (decl)->name);
2970 /* The function recursively processes IR of reservation and defines
2971 max and min cycle for reservation of unit. */
2972 static void
2973 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2974 int min_start_cycle, int *max_finish_cycle,
2975 int *min_finish_cycle)
2977 int i;
2979 switch (regexp->mode)
2981 case rm_unit:
2982 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2983 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2984 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2985 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2986 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2987 *max_finish_cycle = max_start_cycle;
2988 *min_finish_cycle = min_start_cycle;
2989 break;
2991 case rm_reserv:
2992 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2993 max_start_cycle, min_start_cycle,
2994 max_finish_cycle, min_finish_cycle);
2995 break;
2997 case rm_repeat:
2998 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
3000 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
3001 max_start_cycle, min_start_cycle,
3002 max_finish_cycle, min_finish_cycle);
3003 max_start_cycle = *max_finish_cycle + 1;
3004 min_start_cycle = *min_finish_cycle + 1;
3006 break;
3008 case rm_sequence:
3009 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
3011 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
3012 max_start_cycle, min_start_cycle,
3013 max_finish_cycle, min_finish_cycle);
3014 max_start_cycle = *max_finish_cycle + 1;
3015 min_start_cycle = *min_finish_cycle + 1;
3017 break;
3019 case rm_allof:
3021 int max_cycle = 0;
3022 int min_cycle = 0;
3024 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
3026 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
3027 max_start_cycle, min_start_cycle,
3028 max_finish_cycle, min_finish_cycle);
3029 if (max_cycle < *max_finish_cycle)
3030 max_cycle = *max_finish_cycle;
3031 if (i == 0 || min_cycle > *min_finish_cycle)
3032 min_cycle = *min_finish_cycle;
3034 *max_finish_cycle = max_cycle;
3035 *min_finish_cycle = min_cycle;
3037 break;
3039 case rm_oneof:
3041 int max_cycle = 0;
3042 int min_cycle = 0;
3044 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
3046 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
3047 max_start_cycle, min_start_cycle,
3048 max_finish_cycle, min_finish_cycle);
3049 if (max_cycle < *max_finish_cycle)
3050 max_cycle = *max_finish_cycle;
3051 if (i == 0 || min_cycle > *min_finish_cycle)
3052 min_cycle = *min_finish_cycle;
3054 *max_finish_cycle = max_cycle;
3055 *min_finish_cycle = min_cycle;
3057 break;
3059 case rm_nothing:
3060 *max_finish_cycle = max_start_cycle;
3061 *min_finish_cycle = min_start_cycle;
3062 break;
3064 default:
3065 gcc_unreachable ();
3069 /* The following function is called only for correct program. The
3070 function defines max reservation of insns in cycles. */
3071 static void
3072 evaluate_max_reserv_cycles (void)
3074 int max_insn_cycles_num;
3075 int min_insn_cycles_num;
3076 decl_t decl;
3077 int i;
3079 description->max_insn_reserv_cycles = 0;
3080 for (i = 0; i < description->decls_num; i++)
3082 decl = description->decls [i];
3083 if (decl->mode == dm_insn_reserv)
3085 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
3086 &max_insn_cycles_num, &min_insn_cycles_num);
3087 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
3088 description->max_insn_reserv_cycles = max_insn_cycles_num;
3091 description->max_insn_reserv_cycles++;
3094 /* The following function calls functions for checking all
3095 description. */
3096 static void
3097 check_all_description (void)
3099 process_decls ();
3100 check_automaton_usage ();
3101 process_regexp_decls ();
3102 check_usage ();
3103 check_loops_in_regexps ();
3104 if (!have_error)
3105 evaluate_max_reserv_cycles ();
3110 /* The page contains abstract data `ticker'. This data is used to
3111 report time of different phases of building automata. It is
3112 possibly to write a description for which automata will be built
3113 during several minutes even on fast machine. */
3115 /* The following function creates ticker and makes it active. */
3116 static ticker_t
3117 create_ticker (void)
3119 ticker_t ticker;
3121 ticker.modified_creation_time = get_run_time ();
3122 ticker.incremented_off_time = 0;
3123 return ticker;
3126 /* The following function switches off given ticker. */
3127 static void
3128 ticker_off (ticker_t *ticker)
3130 if (ticker->incremented_off_time == 0)
3131 ticker->incremented_off_time = get_run_time () + 1;
3134 /* The following function switches on given ticker. */
3135 static void
3136 ticker_on (ticker_t *ticker)
3138 if (ticker->incremented_off_time != 0)
3140 ticker->modified_creation_time
3141 += get_run_time () - ticker->incremented_off_time + 1;
3142 ticker->incremented_off_time = 0;
3146 /* The following function returns current time in milliseconds since
3147 the moment when given ticker was created. */
3148 static int
3149 active_time (ticker_t ticker)
3151 if (ticker.incremented_off_time != 0)
3152 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3153 else
3154 return get_run_time () - ticker.modified_creation_time;
3157 /* The following function returns string representation of active time
3158 of given ticker. The result is string representation of seconds
3159 with accuracy of 1/100 second. Only result of the last call of the
3160 function exists. Therefore the following code is not correct
3162 printf ("parser time: %s\ngeneration time: %s\n",
3163 active_time_string (parser_ticker),
3164 active_time_string (generation_ticker));
3166 Correct code has to be the following
3168 printf ("parser time: %s\n", active_time_string (parser_ticker));
3169 printf ("generation time: %s\n",
3170 active_time_string (generation_ticker));
3173 static void
3174 print_active_time (FILE *f, ticker_t ticker)
3176 int msecs;
3178 msecs = active_time (ticker);
3179 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3184 /* The following variable value is number of automaton which are
3185 really being created. This value is defined on the base of
3186 argument of option `-split'. If the variable has zero value the
3187 number of automata is defined by the constructions `%automaton'.
3188 This case occurs when option `-split' is absent or has zero
3189 argument. If constructions `define_automaton' is absent only one
3190 automaton is created. */
3191 static int automata_num;
3193 /* The following variable values are times of
3194 o transformation of regular expressions
3195 o building NDFA (DFA if !ndfa_flag)
3196 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3197 o DFA minimization
3198 o building insn equivalence classes
3199 o all previous ones
3200 o code output */
3201 static ticker_t transform_time;
3202 static ticker_t NDFA_time;
3203 static ticker_t NDFA_to_DFA_time;
3204 static ticker_t minimize_time;
3205 static ticker_t equiv_time;
3206 static ticker_t automaton_generation_time;
3207 static ticker_t output_time;
3209 /* The following variable values are times of
3210 all checking
3211 all generation
3212 all pipeline hazard translator work */
3213 static ticker_t check_time;
3214 static ticker_t generation_time;
3215 static ticker_t all_time;
3219 /* Pseudo insn decl which denotes advancing cycle. */
3220 static decl_t advance_cycle_insn_decl;
3221 /* Pseudo insn decl which denotes collapsing the NDFA state. */
3222 static decl_t collapse_ndfa_insn_decl;
3224 /* Create and record a decl for the special advance-cycle transition. */
3225 static void
3226 add_advance_cycle_insn_decl (void)
3228 advance_cycle_insn_decl = XCREATENODE (struct decl);
3229 advance_cycle_insn_decl->mode = dm_insn_reserv;
3230 advance_cycle_insn_decl->pos = no_pos;
3231 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3232 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3233 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3234 = description->insns_num;
3235 description->decls [description->decls_num] = advance_cycle_insn_decl;
3236 description->decls_num++;
3237 description->insns_num++;
3240 /* Create and record a decl for the special collapse-NDFA transition. */
3241 static void
3242 add_collapse_ndfa_insn_decl (void)
3244 collapse_ndfa_insn_decl = XCREATENODE (struct decl);
3245 collapse_ndfa_insn_decl->mode = dm_insn_reserv;
3246 collapse_ndfa_insn_decl->pos = no_pos;
3247 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->regexp = NULL;
3248 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->name = "$collapse_ndfa";
3249 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num
3250 = description->insns_num;
3251 description->decls [description->decls_num] = collapse_ndfa_insn_decl;
3252 description->decls_num++;
3253 description->insns_num++;
3256 /* True if DECL is either of the two special decls we created. */
3257 static bool
3258 special_decl_p (struct insn_reserv_decl *decl)
3260 return (decl == DECL_INSN_RESERV (advance_cycle_insn_decl)
3261 || (collapse_flag
3262 && decl == DECL_INSN_RESERV (collapse_ndfa_insn_decl)));
3266 /* Abstract data `alternative states' which represents
3267 nondeterministic nature of the description (see comments for
3268 structures alt_state and state). */
3270 /* List of free states. */
3271 static alt_state_t first_free_alt_state;
3273 #ifndef NDEBUG
3274 /* The following variables is maximal number of allocated nodes
3275 alt_state. */
3276 static int allocated_alt_states_num = 0;
3277 #endif
3279 /* The following function returns free node alt_state. It may be new
3280 allocated node or node freed earlier. */
3281 static alt_state_t
3282 get_free_alt_state (void)
3284 alt_state_t result;
3286 if (first_free_alt_state != NULL)
3288 result = first_free_alt_state;
3289 first_free_alt_state = first_free_alt_state->next_alt_state;
3291 else
3293 #ifndef NDEBUG
3294 allocated_alt_states_num++;
3295 #endif
3296 result = XCREATENODE (struct alt_state);
3298 result->state = NULL;
3299 result->next_alt_state = NULL;
3300 result->next_sorted_alt_state = NULL;
3301 return result;
3304 /* The function frees node ALT_STATE. */
3305 static void
3306 free_alt_state (alt_state_t alt_state)
3308 if (alt_state == NULL)
3309 return;
3310 alt_state->next_alt_state = first_free_alt_state;
3311 first_free_alt_state = alt_state;
3314 /* The function frees list started with node ALT_STATE_LIST. */
3315 static void
3316 free_alt_states (alt_state_t alt_states_list)
3318 alt_state_t curr_alt_state;
3319 alt_state_t next_alt_state;
3321 for (curr_alt_state = alt_states_list;
3322 curr_alt_state != NULL;
3323 curr_alt_state = next_alt_state)
3325 next_alt_state = curr_alt_state->next_alt_state;
3326 free_alt_state (curr_alt_state);
3330 /* The function compares unique numbers of alt states. */
3331 static int
3332 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3334 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3335 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3336 return 0;
3337 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3338 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3339 return -1;
3340 else
3341 return 1;
3344 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3345 states from the list. The comparison key is alt state unique
3346 number. */
3348 static alt_state_t
3349 uniq_sort_alt_states (alt_state_t alt_states_list)
3351 alt_state_t curr_alt_state;
3352 VEC(alt_state_t, heap) *alt_states;
3353 size_t i;
3354 size_t prev_unique_state_ind;
3355 alt_state_t result;
3357 if (alt_states_list == 0)
3358 return 0;
3359 if (alt_states_list->next_alt_state == 0)
3360 return alt_states_list;
3362 alt_states = VEC_alloc (alt_state_t, heap, 150);
3363 for (curr_alt_state = alt_states_list;
3364 curr_alt_state != NULL;
3365 curr_alt_state = curr_alt_state->next_alt_state)
3366 VEC_safe_push (alt_state_t, heap, alt_states, curr_alt_state);
3368 VEC_qsort (alt_state_t, alt_states, alt_state_cmp);
3370 prev_unique_state_ind = 0;
3371 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3372 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3373 != VEC_index (alt_state_t, alt_states, i)->state)
3375 prev_unique_state_ind++;
3376 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3377 VEC_index (alt_state_t, alt_states, i));
3379 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3381 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3382 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3383 = VEC_index (alt_state_t, alt_states, i);
3384 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3386 result = VEC_index (alt_state_t, alt_states, 0);
3388 VEC_free (alt_state_t, heap, alt_states);
3389 return result;
3392 /* The function checks equality of alt state lists. Remember that the
3393 lists must be already sorted by the previous function. */
3394 static int
3395 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3397 while (alt_states_1 != NULL && alt_states_2 != NULL
3398 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3400 alt_states_1 = alt_states_1->next_sorted_alt_state;
3401 alt_states_2 = alt_states_2->next_sorted_alt_state;
3403 return alt_states_1 == alt_states_2;
3406 /* Initialization of the abstract data. */
3407 static void
3408 initiate_alt_states (void)
3410 first_free_alt_state = NULL;
3413 /* Finishing work with the abstract data. */
3414 static void
3415 finish_alt_states (void)
3421 /* The page contains macros for work with bits strings. We could use
3422 standard gcc bitmap or sbitmap but it would result in difficulties
3423 of building canadian cross. */
3425 /* Set bit number bitno in the bit string. The macro is not side
3426 effect proof. */
3427 #define SET_BIT(bitstring, bitno) \
3428 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] |= \
3429 (HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT))
3431 #define CLEAR_BIT(bitstring, bitno) \
3432 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] &= \
3433 ~((HOST_WIDE_INT)1 << (bitno) % (sizeof (*(bitstring)) * CHAR_BIT)))
3435 /* Test if bit number bitno in the bitstring is set. The macro is not
3436 side effect proof. */
3437 #define TEST_BIT(bitstring, bitno) \
3438 ((bitstring)[(bitno) / (sizeof (*(bitstring)) * CHAR_BIT)] >> \
3439 (bitno) % (sizeof (*(bitstring)) * CHAR_BIT) & 1)
3443 /* This page contains abstract data `state'. */
3445 /* Maximal length of reservations in cycles (>= 1). */
3446 static int max_cycles_num;
3448 /* Number of set elements (see type set_el_t) needed for
3449 representation of one cycle reservation. It is depended on units
3450 number. */
3451 static int els_in_cycle_reserv;
3453 /* Number of set elements (see type set_el_t) needed for
3454 representation of maximal length reservation. Deterministic
3455 reservation is stored as set (bit string) of length equal to the
3456 variable value * number of bits in set_el_t. */
3457 static int els_in_reservs;
3459 /* Array of pointers to unit declarations. */
3460 static unit_decl_t *units_array;
3462 /* Temporary reservation of maximal length. */
3463 static reserv_sets_t temp_reserv;
3465 /* The state table itself is represented by the following variable. */
3466 static htab_t state_table;
3468 /* Linked list of free 'state' structures to be recycled. The
3469 next_equiv_class_state pointer is borrowed for a free list. */
3470 static state_t first_free_state;
3472 static int curr_unique_state_num;
3474 #ifndef NDEBUG
3475 /* The following variables is maximal number of allocated nodes
3476 `state'. */
3477 static int allocated_states_num = 0;
3478 #endif
3480 /* Allocate new reservation set. */
3481 static reserv_sets_t
3482 alloc_empty_reserv_sets (void)
3484 reserv_sets_t result;
3486 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3487 result = (reserv_sets_t) obstack_base (&irp);
3488 obstack_finish (&irp);
3489 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3490 return result;
3493 /* Hash value of reservation set. */
3494 static unsigned
3495 reserv_sets_hash_value (reserv_sets_t reservs)
3497 set_el_t hash_value;
3498 unsigned result;
3499 int reservs_num, i;
3500 set_el_t *reserv_ptr;
3502 hash_value = 0;
3503 reservs_num = els_in_reservs;
3504 reserv_ptr = reservs;
3505 i = 0;
3506 while (reservs_num != 0)
3508 reservs_num--;
3509 hash_value += ((*reserv_ptr >> i)
3510 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3511 i++;
3512 if (i == sizeof (set_el_t) * CHAR_BIT)
3513 i = 0;
3514 reserv_ptr++;
3516 if (sizeof (set_el_t) <= sizeof (unsigned))
3517 return hash_value;
3518 result = 0;
3519 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3521 result += (unsigned) hash_value;
3522 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3524 return result;
3527 /* Comparison of given reservation sets. */
3528 static int
3529 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3531 int reservs_num;
3532 const set_el_t *reserv_ptr_1;
3533 const set_el_t *reserv_ptr_2;
3535 gcc_assert (reservs_1 && reservs_2);
3536 reservs_num = els_in_reservs;
3537 reserv_ptr_1 = reservs_1;
3538 reserv_ptr_2 = reservs_2;
3539 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3541 reservs_num--;
3542 reserv_ptr_1++;
3543 reserv_ptr_2++;
3545 if (reservs_num == 0)
3546 return 0;
3547 else if (*reserv_ptr_1 < *reserv_ptr_2)
3548 return -1;
3549 else
3550 return 1;
3553 /* The function checks equality of the reservation sets. */
3554 static int
3555 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3557 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3560 /* Set up in the reservation set that unit with UNIT_NUM is used on
3561 CYCLE_NUM. */
3562 static void
3563 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3565 gcc_assert (cycle_num < max_cycles_num);
3566 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3567 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3570 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3571 used on CYCLE_NUM. */
3572 static int
3573 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3575 gcc_assert (cycle_num < max_cycles_num);
3576 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3577 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3580 /* The function checks that the reservation sets are intersected,
3581 i.e. there is a unit reservation on a cycle in both reservation
3582 sets. */
3583 static int
3584 reserv_sets_are_intersected (reserv_sets_t operand_1,
3585 reserv_sets_t operand_2)
3587 set_el_t *el_ptr_1;
3588 set_el_t *el_ptr_2;
3589 set_el_t *cycle_ptr_1;
3590 set_el_t *cycle_ptr_2;
3592 gcc_assert (operand_1 && operand_2);
3593 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3594 el_ptr_1 < operand_1 + els_in_reservs;
3595 el_ptr_1++, el_ptr_2++)
3596 if (*el_ptr_1 & *el_ptr_2)
3597 return 1;
3598 reserv_sets_or (temp_reserv, operand_1, operand_2);
3599 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3600 cycle_ptr_1 < operand_1 + els_in_reservs;
3601 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3603 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3604 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3605 el_ptr_1++, el_ptr_2++)
3606 if (*el_ptr_1 & *el_ptr_2)
3607 return 1;
3608 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3609 return 1;
3610 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3611 - operand_2),
3612 cycle_ptr_2, TRUE))
3613 return 1;
3614 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3615 return 1;
3616 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3617 cycle_ptr_2, TRUE))
3618 return 1;
3620 return 0;
3623 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3624 cpu cycle. The remaining bits of OPERAND (representing the last
3625 cycle unit reservations) are not changed. */
3626 static void
3627 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3629 int i;
3631 gcc_assert (result && operand && result != operand);
3632 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3633 result [i - els_in_cycle_reserv] = operand [i];
3636 /* OR of the reservation sets. */
3637 static void
3638 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3639 reserv_sets_t operand_2)
3641 set_el_t *el_ptr_1;
3642 set_el_t *el_ptr_2;
3643 set_el_t *result_set_el_ptr;
3645 gcc_assert (result && operand_1 && operand_2);
3646 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3647 el_ptr_1 < operand_1 + els_in_reservs;
3648 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3649 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3652 /* AND of the reservation sets. */
3653 static void
3654 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3655 reserv_sets_t operand_2)
3657 set_el_t *el_ptr_1;
3658 set_el_t *el_ptr_2;
3659 set_el_t *result_set_el_ptr;
3661 gcc_assert (result && operand_1 && operand_2);
3662 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3663 el_ptr_1 < operand_1 + els_in_reservs;
3664 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3665 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3668 /* The function outputs string representation of units reservation on
3669 cycle START_CYCLE in the reservation set. The function uses repeat
3670 construction if REPETITION_NUM > 1. */
3671 static void
3672 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3673 int repetition_num)
3675 int unit_num;
3676 int reserved_units_num;
3678 reserved_units_num = 0;
3679 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3680 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3681 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3682 reserved_units_num++;
3683 gcc_assert (repetition_num > 0);
3684 if (repetition_num != 1 && reserved_units_num > 1)
3685 fprintf (f, "(");
3686 reserved_units_num = 0;
3687 for (unit_num = 0;
3688 unit_num < description->units_num;
3689 unit_num++)
3690 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3691 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3693 if (reserved_units_num != 0)
3694 fprintf (f, "+");
3695 reserved_units_num++;
3696 fprintf (f, "%s", units_array [unit_num]->name);
3698 if (reserved_units_num == 0)
3699 fprintf (f, NOTHING_NAME);
3700 gcc_assert (repetition_num > 0);
3701 if (repetition_num != 1 && reserved_units_num > 1)
3702 fprintf (f, ")");
3703 if (repetition_num != 1)
3704 fprintf (f, "*%d", repetition_num);
3707 /* The function outputs string representation of units reservation in
3708 the reservation set. */
3709 static void
3710 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3712 int start_cycle = 0;
3713 int cycle;
3714 int repetition_num;
3716 repetition_num = 0;
3717 for (cycle = 0; cycle < max_cycles_num; cycle++)
3718 if (repetition_num == 0)
3720 repetition_num++;
3721 start_cycle = cycle;
3723 else if (memcmp
3724 ((char *) reservs + start_cycle * els_in_cycle_reserv
3725 * sizeof (set_el_t),
3726 (char *) reservs + cycle * els_in_cycle_reserv
3727 * sizeof (set_el_t),
3728 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3729 repetition_num++;
3730 else
3732 if (start_cycle != 0)
3733 fprintf (f, ", ");
3734 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3735 repetition_num = 1;
3736 start_cycle = cycle;
3738 if (start_cycle < max_cycles_num)
3740 if (start_cycle != 0)
3741 fprintf (f, ", ");
3742 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3746 /* The following function returns free node state for AUTOMATON. It
3747 may be new allocated node or node freed earlier. The function also
3748 allocates reservation set if WITH_RESERVS has nonzero value. */
3749 static state_t
3750 get_free_state (int with_reservs, automaton_t automaton)
3752 state_t result;
3754 gcc_assert (max_cycles_num > 0 && automaton);
3755 if (first_free_state)
3757 result = first_free_state;
3758 first_free_state = result->next_equiv_class_state;
3760 result->next_equiv_class_state = NULL;
3761 result->automaton = automaton;
3762 result->first_out_arc = NULL;
3763 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3764 result->it_was_placed_in_stack_for_DFA_forming = 0;
3765 result->component_states = NULL;
3767 else
3769 #ifndef NDEBUG
3770 allocated_states_num++;
3771 #endif
3772 result = XCREATENODE (struct state);
3773 result->automaton = automaton;
3774 result->first_out_arc = NULL;
3775 result->unique_num = curr_unique_state_num;
3776 curr_unique_state_num++;
3778 if (with_reservs)
3780 if (result->reservs == NULL)
3781 result->reservs = alloc_empty_reserv_sets ();
3782 else
3783 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3785 return result;
3788 /* The function frees node STATE. */
3789 static void
3790 free_state (state_t state)
3792 free_alt_states (state->component_states);
3793 state->next_equiv_class_state = first_free_state;
3794 first_free_state = state;
3797 /* Hash value of STATE. If STATE represents deterministic state it is
3798 simply hash value of the corresponding reservation set. Otherwise
3799 it is formed from hash values of the component deterministic
3800 states. One more key is order number of state automaton. */
3801 static hashval_t
3802 state_hash (const void *state)
3804 unsigned int hash_value;
3805 alt_state_t alt_state;
3807 if (((const_state_t) state)->component_states == NULL)
3808 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3809 else
3811 hash_value = 0;
3812 for (alt_state = ((const_state_t) state)->component_states;
3813 alt_state != NULL;
3814 alt_state = alt_state->next_sorted_alt_state)
3815 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3816 | (hash_value << CHAR_BIT))
3817 + alt_state->state->unique_num);
3819 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3820 | (hash_value << CHAR_BIT))
3821 + ((const_state_t) state)->automaton->automaton_order_num);
3822 return hash_value;
3825 /* Return nonzero value if the states are the same. */
3826 static int
3827 state_eq_p (const void *state_1, const void *state_2)
3829 alt_state_t alt_state_1;
3830 alt_state_t alt_state_2;
3832 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3833 return 0;
3834 else if (((const_state_t) state_1)->component_states == NULL
3835 && ((const_state_t) state_2)->component_states == NULL)
3836 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3837 ((const_state_t) state_2)->reservs);
3838 else if (((const_state_t) state_1)->component_states != NULL
3839 && ((const_state_t) state_2)->component_states != NULL)
3841 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3842 alt_state_2 = ((const_state_t) state_2)->component_states;
3843 alt_state_1 != NULL && alt_state_2 != NULL;
3844 alt_state_1 = alt_state_1->next_sorted_alt_state,
3845 alt_state_2 = alt_state_2->next_sorted_alt_state)
3846 /* All state in the list must be already in the hash table.
3847 Also the lists must be sorted. */
3848 if (alt_state_1->state != alt_state_2->state)
3849 return 0;
3850 return alt_state_1 == alt_state_2;
3852 else
3853 return 0;
3856 /* Insert STATE into the state table. */
3857 static state_t
3858 insert_state (state_t state)
3860 void **entry_ptr;
3862 entry_ptr = htab_find_slot (state_table, (void *) state, INSERT);
3863 if (*entry_ptr == NULL)
3864 *entry_ptr = (void *) state;
3865 return (state_t) *entry_ptr;
3868 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3869 deterministic STATE. */
3870 static void
3871 set_state_reserv (state_t state, int cycle_num, int unit_num)
3873 set_unit_reserv (state->reservs, cycle_num, unit_num);
3876 /* Return nonzero value if the deterministic states contains a
3877 reservation of the same cpu unit on the same cpu cycle. */
3878 static int
3879 intersected_state_reservs_p (state_t state1, state_t state2)
3881 gcc_assert (state1->automaton == state2->automaton);
3882 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3885 /* Return deterministic state (inserted into the table) which
3886 representing the automaton state which is union of reservations of
3887 the deterministic states masked by RESERVS. */
3888 static state_t
3889 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3891 state_t result;
3892 state_t state_in_table;
3894 gcc_assert (state1->automaton == state2->automaton);
3895 result = get_free_state (1, state1->automaton);
3896 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3897 reserv_sets_and (result->reservs, result->reservs, reservs);
3898 state_in_table = insert_state (result);
3899 if (result != state_in_table)
3901 free_state (result);
3902 result = state_in_table;
3904 return result;
3907 /* Return deterministic state (inserted into the table) which
3908 represent the automaton state is obtained from deterministic STATE
3909 by advancing cpu cycle and masking by RESERVS. */
3910 static state_t
3911 state_shift (state_t state, reserv_sets_t reservs)
3913 state_t result;
3914 state_t state_in_table;
3916 result = get_free_state (1, state->automaton);
3917 reserv_sets_shift (result->reservs, state->reservs);
3918 reserv_sets_and (result->reservs, result->reservs, reservs);
3919 state_in_table = insert_state (result);
3920 if (result != state_in_table)
3922 free_state (result);
3923 result = state_in_table;
3925 return result;
3928 /* Initialization of the abstract data. */
3929 static void
3930 initiate_states (void)
3932 decl_t decl;
3933 int i;
3935 if (description->units_num)
3936 units_array = XNEWVEC (unit_decl_t, description->units_num);
3937 else
3938 units_array = 0;
3940 for (i = 0; i < description->decls_num; i++)
3942 decl = description->decls [i];
3943 if (decl->mode == dm_unit)
3944 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3946 max_cycles_num = description->max_insn_reserv_cycles;
3947 els_in_cycle_reserv
3948 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3949 / (sizeof (set_el_t) * CHAR_BIT));
3950 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3951 curr_unique_state_num = 0;
3952 initiate_alt_states ();
3953 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3954 temp_reserv = alloc_empty_reserv_sets ();
3957 /* Finishing work with the abstract data. */
3958 static void
3959 finish_states (void)
3961 free (units_array);
3962 units_array = 0;
3963 htab_delete (state_table);
3964 first_free_state = NULL;
3965 finish_alt_states ();
3970 /* Abstract data `arcs'. */
3972 /* List of free arcs. */
3973 static arc_t first_free_arc;
3975 #ifndef NDEBUG
3976 /* The following variables is maximal number of allocated nodes
3977 `arc'. */
3978 static int allocated_arcs_num = 0;
3979 #endif
3981 /* The function frees node ARC. */
3982 static void
3983 free_arc (arc_t arc)
3985 arc->next_out_arc = first_free_arc;
3986 first_free_arc = arc;
3989 /* The function removes and frees ARC staring from FROM_STATE. */
3990 static void
3991 remove_arc (state_t from_state, arc_t arc)
3993 arc_t prev_arc;
3994 arc_t curr_arc;
3996 gcc_assert (arc);
3997 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3998 curr_arc != NULL;
3999 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
4000 if (curr_arc == arc)
4001 break;
4002 gcc_assert (curr_arc);
4003 if (prev_arc == NULL)
4004 from_state->first_out_arc = arc->next_out_arc;
4005 else
4006 prev_arc->next_out_arc = arc->next_out_arc;
4007 from_state->num_out_arcs--;
4008 free_arc (arc);
4011 /* The functions returns arc with given characteristics (or NULL if
4012 the arc does not exist). */
4013 static arc_t
4014 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
4016 arc_t arc;
4018 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
4019 if (arc->insn == insn
4020 && (arc->to_state == to_state
4021 || (collapse_flag
4022 /* Any arc is good enough for a collapse-ndfa transition. */
4023 && (insn->insn_reserv_decl
4024 == DECL_INSN_RESERV (collapse_ndfa_insn_decl)))))
4025 return arc;
4026 return NULL;
4029 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN,
4030 unless such an arc already exists. */
4031 static void
4032 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
4034 arc_t new_arc;
4036 new_arc = find_arc (from_state, to_state, ainsn);
4037 if (new_arc != NULL)
4038 return;
4039 if (first_free_arc == NULL)
4041 #ifndef NDEBUG
4042 allocated_arcs_num++;
4043 #endif
4044 new_arc = XCREATENODE (struct arc);
4045 new_arc->to_state = NULL;
4046 new_arc->insn = NULL;
4047 new_arc->next_out_arc = NULL;
4049 else
4051 new_arc = first_free_arc;
4052 first_free_arc = first_free_arc->next_out_arc;
4054 new_arc->to_state = to_state;
4055 new_arc->insn = ainsn;
4056 ainsn->arc_exists_p = 1;
4057 new_arc->next_out_arc = from_state->first_out_arc;
4058 from_state->first_out_arc = new_arc;
4059 from_state->num_out_arcs++;
4060 new_arc->next_arc_marked_by_insn = NULL;
4063 /* The function returns the first arc starting from STATE. */
4064 static arc_t
4065 first_out_arc (const_state_t state)
4067 return state->first_out_arc;
4070 /* The function returns next out arc after ARC. */
4071 static arc_t
4072 next_out_arc (arc_t arc)
4074 return arc->next_out_arc;
4077 /* Initialization of the abstract data. */
4078 static void
4079 initiate_arcs (void)
4081 first_free_arc = NULL;
4084 /* Finishing work with the abstract data. */
4085 static void
4086 finish_arcs (void)
4092 /* Abstract data `automata lists'. */
4094 /* List of free states. */
4095 static automata_list_el_t first_free_automata_list_el;
4097 /* The list being formed. */
4098 static automata_list_el_t current_automata_list;
4100 /* Hash table of automata lists. */
4101 static htab_t automata_list_table;
4103 /* The following function returns free automata list el. It may be
4104 new allocated node or node freed earlier. */
4105 static automata_list_el_t
4106 get_free_automata_list_el (void)
4108 automata_list_el_t result;
4110 if (first_free_automata_list_el != NULL)
4112 result = first_free_automata_list_el;
4113 first_free_automata_list_el
4114 = first_free_automata_list_el->next_automata_list_el;
4116 else
4117 result = XCREATENODE (struct automata_list_el);
4118 result->automaton = NULL;
4119 result->next_automata_list_el = NULL;
4120 return result;
4123 /* The function frees node AUTOMATA_LIST_EL. */
4124 static void
4125 free_automata_list_el (automata_list_el_t automata_list_el)
4127 if (automata_list_el == NULL)
4128 return;
4129 automata_list_el->next_automata_list_el = first_free_automata_list_el;
4130 first_free_automata_list_el = automata_list_el;
4133 /* The function frees list AUTOMATA_LIST. */
4134 static void
4135 free_automata_list (automata_list_el_t automata_list)
4137 automata_list_el_t curr_automata_list_el;
4138 automata_list_el_t next_automata_list_el;
4140 for (curr_automata_list_el = automata_list;
4141 curr_automata_list_el != NULL;
4142 curr_automata_list_el = next_automata_list_el)
4144 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4145 free_automata_list_el (curr_automata_list_el);
4149 /* Hash value of AUTOMATA_LIST. */
4150 static hashval_t
4151 automata_list_hash (const void *automata_list)
4153 unsigned int hash_value;
4154 const_automata_list_el_t curr_automata_list_el;
4156 hash_value = 0;
4157 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4158 curr_automata_list_el != NULL;
4159 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4160 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4161 | (hash_value << CHAR_BIT))
4162 + curr_automata_list_el->automaton->automaton_order_num);
4163 return hash_value;
4166 /* Return nonzero value if the automata_lists are the same. */
4167 static int
4168 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4170 const_automata_list_el_t automata_list_el_1;
4171 const_automata_list_el_t automata_list_el_2;
4173 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4174 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4175 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4176 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4177 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4178 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4179 return 0;
4180 return automata_list_el_1 == automata_list_el_2;
4183 /* Initialization of the abstract data. */
4184 static void
4185 initiate_automata_lists (void)
4187 first_free_automata_list_el = NULL;
4188 automata_list_table = htab_create (1500, automata_list_hash,
4189 automata_list_eq_p, (htab_del) 0);
4192 /* The following function starts new automata list and makes it the
4193 current one. */
4194 static void
4195 automata_list_start (void)
4197 current_automata_list = NULL;
4200 /* The following function adds AUTOMATON to the current list. */
4201 static void
4202 automata_list_add (automaton_t automaton)
4204 automata_list_el_t el;
4206 el = get_free_automata_list_el ();
4207 el->automaton = automaton;
4208 el->next_automata_list_el = current_automata_list;
4209 current_automata_list = el;
4212 /* The following function finishes forming the current list, inserts
4213 it into the table and returns it. */
4214 static automata_list_el_t
4215 automata_list_finish (void)
4217 void **entry_ptr;
4219 if (current_automata_list == NULL)
4220 return NULL;
4221 entry_ptr = htab_find_slot (automata_list_table,
4222 (void *) current_automata_list, INSERT);
4223 if (*entry_ptr == NULL)
4224 *entry_ptr = (void *) current_automata_list;
4225 else
4226 free_automata_list (current_automata_list);
4227 current_automata_list = NULL;
4228 return (automata_list_el_t) *entry_ptr;
4231 /* Finishing work with the abstract data. */
4232 static void
4233 finish_automata_lists (void)
4235 htab_delete (automata_list_table);
4240 /* The page contains abstract data for work with exclusion sets (see
4241 exclusion_set in file rtl.def). */
4243 /* The following variable refers to an exclusion set returned by
4244 get_excl_set. This is bit string of length equal to cpu units
4245 number. If exclusion set for given unit contains 1 for a unit,
4246 then simultaneous reservation of the units is prohibited. */
4247 static reserv_sets_t excl_set;
4249 /* The array contains exclusion sets for each unit. */
4250 static reserv_sets_t *unit_excl_set_table;
4252 /* The following function forms the array containing exclusion sets
4253 for each unit. */
4254 static void
4255 initiate_excl_sets (void)
4257 decl_t decl;
4258 reserv_sets_t unit_excl_set;
4259 unit_set_el_t el;
4260 int i;
4262 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4263 excl_set = (reserv_sets_t) obstack_base (&irp);
4264 obstack_finish (&irp);
4265 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4266 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4267 obstack_finish (&irp);
4268 /* Evaluate unit exclusion sets. */
4269 for (i = 0; i < description->decls_num; i++)
4271 decl = description->decls [i];
4272 if (decl->mode == dm_unit)
4274 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4275 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4276 obstack_finish (&irp);
4277 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4278 for (el = DECL_UNIT (decl)->excl_list;
4279 el != NULL;
4280 el = el->next_unit_set_el)
4282 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4283 el->unit_decl->in_set_p = TRUE;
4285 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4290 /* The function sets up and return EXCL_SET which is union of
4291 exclusion sets for each unit in IN_SET. */
4292 static reserv_sets_t
4293 get_excl_set (reserv_sets_t in_set)
4295 int el;
4296 unsigned int i;
4297 int start_unit_num;
4298 int unit_num;
4300 memset (excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4301 for (el = 0; el < els_in_cycle_reserv; el++)
4302 if (in_set[el])
4303 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4304 if ((in_set[el] >> i) & 1)
4306 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4307 if (start_unit_num >= description->units_num)
4308 return excl_set;
4309 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4311 excl_set [unit_num]
4312 |= unit_excl_set_table [start_unit_num] [unit_num];
4315 return excl_set;
4320 /* The page contains abstract data for work with presence/absence
4321 pattern sets (see presence_set/absence_set in file rtl.def). */
4323 /* The following arrays contain correspondingly presence, final
4324 presence, absence, and final absence patterns for each unit. */
4325 static pattern_reserv_t *unit_presence_set_table;
4326 static pattern_reserv_t *unit_final_presence_set_table;
4327 static pattern_reserv_t *unit_absence_set_table;
4328 static pattern_reserv_t *unit_final_absence_set_table;
4330 /* The following function forms list of reservation sets for given
4331 PATTERN_LIST. */
4332 static pattern_reserv_t
4333 form_reserv_sets_list (pattern_set_el_t pattern_list)
4335 pattern_set_el_t el;
4336 pattern_reserv_t first, curr, prev;
4337 int i;
4339 prev = first = NULL;
4340 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4342 curr = XCREATENODE (struct pattern_reserv);
4343 curr->reserv = alloc_empty_reserv_sets ();
4344 curr->next_pattern_reserv = NULL;
4345 for (i = 0; i < el->units_num; i++)
4347 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4348 el->unit_decls [i]->in_set_p = TRUE;
4350 if (prev != NULL)
4351 prev->next_pattern_reserv = curr;
4352 else
4353 first = curr;
4354 prev = curr;
4356 return first;
4359 /* The following function forms the array containing presence and
4360 absence pattern sets for each unit. */
4361 static void
4362 initiate_presence_absence_pattern_sets (void)
4364 decl_t decl;
4365 int i;
4367 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4368 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4369 obstack_finish (&irp);
4370 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4371 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4372 obstack_finish (&irp);
4373 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4374 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4375 obstack_finish (&irp);
4376 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4377 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4378 obstack_finish (&irp);
4379 /* Evaluate unit presence/absence sets. */
4380 for (i = 0; i < description->decls_num; i++)
4382 decl = description->decls [i];
4383 if (decl->mode == dm_unit)
4385 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4386 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4387 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4388 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4389 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4390 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4391 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4392 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4397 /* The function checks that CHECKED_SET satisfies all presence pattern
4398 sets for units in ORIGINAL_SET. The function returns TRUE if it
4399 is ok. */
4400 static int
4401 check_presence_pattern_sets (reserv_sets_t checked_set,
4402 reserv_sets_t original_set,
4403 int final_p)
4405 int el;
4406 unsigned int i;
4407 int start_unit_num;
4408 int unit_num;
4409 int presence_p;
4410 pattern_reserv_t pat_reserv;
4412 for (el = 0; el < els_in_cycle_reserv; el++)
4413 if (original_set[el])
4414 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4415 if ((original_set[el] >> i) & 1)
4417 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4418 if (start_unit_num >= description->units_num)
4419 break;
4420 if ((final_p
4421 && unit_final_presence_set_table [start_unit_num] == NULL)
4422 || (!final_p
4423 && unit_presence_set_table [start_unit_num] == NULL))
4424 continue;
4425 presence_p = FALSE;
4426 for (pat_reserv = (final_p
4427 ? unit_final_presence_set_table [start_unit_num]
4428 : unit_presence_set_table [start_unit_num]);
4429 pat_reserv != NULL;
4430 pat_reserv = pat_reserv->next_pattern_reserv)
4432 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4433 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4434 != pat_reserv->reserv [unit_num])
4435 break;
4436 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4438 if (!presence_p)
4439 return FALSE;
4441 return TRUE;
4444 /* The function checks that CHECKED_SET satisfies all absence pattern
4445 sets for units in ORIGINAL_SET. The function returns TRUE if it
4446 is ok. */
4447 static int
4448 check_absence_pattern_sets (reserv_sets_t checked_set,
4449 reserv_sets_t original_set,
4450 int final_p)
4452 int el;
4453 unsigned int i;
4454 int start_unit_num;
4455 int unit_num;
4456 pattern_reserv_t pat_reserv;
4458 for (el = 0; el < els_in_cycle_reserv; el++)
4459 if (original_set[el])
4460 for (i = 0; i < CHAR_BIT * sizeof (set_el_t); i++)
4461 if ((original_set[el] >> i) & 1)
4463 start_unit_num = el * CHAR_BIT * sizeof (set_el_t) + i;
4464 if (start_unit_num >= description->units_num)
4465 break;
4466 for (pat_reserv = (final_p
4467 ? unit_final_absence_set_table [start_unit_num]
4468 : unit_absence_set_table [start_unit_num]);
4469 pat_reserv != NULL;
4470 pat_reserv = pat_reserv->next_pattern_reserv)
4472 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4473 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4474 != pat_reserv->reserv [unit_num]
4475 && pat_reserv->reserv [unit_num])
4476 break;
4477 if (unit_num >= els_in_cycle_reserv)
4478 return FALSE;
4481 return TRUE;
4486 /* This page contains code for transformation of original reservations
4487 described in .md file. The main goal of transformations is
4488 simplifying reservation and lifting up all `|' on the top of IR
4489 reservation representation. */
4492 /* The following function makes copy of IR representation of
4493 reservation. The function also substitutes all reservations
4494 defined by define_reservation by corresponding value during making
4495 the copy. */
4496 static regexp_t
4497 copy_insn_regexp (regexp_t regexp)
4499 regexp_t result;
4500 int i;
4502 switch (regexp->mode)
4504 case rm_reserv:
4505 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4506 break;
4508 case rm_unit:
4509 result = XCOPYNODE (struct regexp, regexp);
4510 break;
4512 case rm_repeat:
4513 result = XCOPYNODE (struct regexp, regexp);
4514 REGEXP_REPEAT (result)->regexp
4515 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4516 break;
4518 case rm_sequence:
4519 result = XCOPYNODEVAR (struct regexp, regexp,
4520 sizeof (struct regexp) + sizeof (regexp_t)
4521 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4522 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4523 REGEXP_SEQUENCE (result)->regexps [i]
4524 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4525 break;
4527 case rm_allof:
4528 result = XCOPYNODEVAR (struct regexp, regexp,
4529 sizeof (struct regexp) + sizeof (regexp_t)
4530 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4531 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4532 REGEXP_ALLOF (result)->regexps [i]
4533 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4534 break;
4536 case rm_oneof:
4537 result = XCOPYNODEVAR (struct regexp, regexp,
4538 sizeof (struct regexp) + sizeof (regexp_t)
4539 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4540 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4541 REGEXP_ONEOF (result)->regexps [i]
4542 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4543 break;
4545 case rm_nothing:
4546 result = XCOPYNODE (struct regexp, regexp);
4547 break;
4549 default:
4550 gcc_unreachable ();
4552 return result;
4555 /* The following variable is set up 1 if a transformation has been
4556 applied. */
4557 static int regexp_transformed_p;
4559 /* The function makes transformation
4560 A*N -> A, A, ... */
4561 static regexp_t
4562 transform_1 (regexp_t regexp)
4564 int i;
4565 int repeat_num;
4566 regexp_t operand;
4567 pos_t pos;
4569 if (regexp->mode == rm_repeat)
4571 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4572 gcc_assert (repeat_num > 1);
4573 operand = REGEXP_REPEAT (regexp)->regexp;
4574 pos = regexp->mode;
4575 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4576 + sizeof (regexp_t) * (repeat_num - 1));
4577 regexp->mode = rm_sequence;
4578 regexp->pos = pos;
4579 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4580 for (i = 0; i < repeat_num; i++)
4581 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4582 regexp_transformed_p = 1;
4584 return regexp;
4587 /* The function makes transformations
4588 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4589 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4590 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4591 static regexp_t
4592 transform_2 (regexp_t regexp)
4594 if (regexp->mode == rm_sequence)
4596 regexp_t sequence = NULL;
4597 regexp_t result;
4598 int sequence_index = 0;
4599 int i, j;
4601 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4602 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4604 sequence_index = i;
4605 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4606 break;
4608 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4610 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4611 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4612 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4613 + sizeof (regexp_t)
4614 * (REGEXP_SEQUENCE (regexp)->regexps_num
4615 + REGEXP_SEQUENCE (sequence)->regexps_num
4616 - 2));
4617 result->mode = rm_sequence;
4618 result->pos = regexp->pos;
4619 REGEXP_SEQUENCE (result)->regexps_num
4620 = (REGEXP_SEQUENCE (regexp)->regexps_num
4621 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4622 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4623 if (i < sequence_index)
4624 REGEXP_SEQUENCE (result)->regexps [i]
4625 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4626 else if (i > sequence_index)
4627 REGEXP_SEQUENCE (result)->regexps
4628 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4629 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4630 else
4631 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4632 REGEXP_SEQUENCE (result)->regexps [i + j]
4633 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4634 regexp_transformed_p = 1;
4635 regexp = result;
4638 else if (regexp->mode == rm_allof)
4640 regexp_t allof = NULL;
4641 regexp_t result;
4642 int allof_index = 0;
4643 int i, j;
4645 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4646 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4648 allof_index = i;
4649 allof = REGEXP_ALLOF (regexp)->regexps [i];
4650 break;
4652 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4654 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4655 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4656 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4657 + sizeof (regexp_t)
4658 * (REGEXP_ALLOF (regexp)->regexps_num
4659 + REGEXP_ALLOF (allof)->regexps_num - 2));
4660 result->mode = rm_allof;
4661 result->pos = regexp->pos;
4662 REGEXP_ALLOF (result)->regexps_num
4663 = (REGEXP_ALLOF (regexp)->regexps_num
4664 + REGEXP_ALLOF (allof)->regexps_num - 1);
4665 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4666 if (i < allof_index)
4667 REGEXP_ALLOF (result)->regexps [i]
4668 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4669 else if (i > allof_index)
4670 REGEXP_ALLOF (result)->regexps
4671 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4672 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4673 else
4674 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4675 REGEXP_ALLOF (result)->regexps [i + j]
4676 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4677 regexp_transformed_p = 1;
4678 regexp = result;
4681 else if (regexp->mode == rm_oneof)
4683 regexp_t oneof = NULL;
4684 regexp_t result;
4685 int oneof_index = 0;
4686 int i, j;
4688 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4689 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4691 oneof_index = i;
4692 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4693 break;
4695 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4697 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4698 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4699 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4700 + sizeof (regexp_t)
4701 * (REGEXP_ONEOF (regexp)->regexps_num
4702 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4703 result->mode = rm_oneof;
4704 result->pos = regexp->pos;
4705 REGEXP_ONEOF (result)->regexps_num
4706 = (REGEXP_ONEOF (regexp)->regexps_num
4707 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4708 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4709 if (i < oneof_index)
4710 REGEXP_ONEOF (result)->regexps [i]
4711 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4712 else if (i > oneof_index)
4713 REGEXP_ONEOF (result)->regexps
4714 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4715 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4716 else
4717 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4718 REGEXP_ONEOF (result)->regexps [i + j]
4719 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4720 regexp_transformed_p = 1;
4721 regexp = result;
4724 return regexp;
4727 /* The function makes transformations
4728 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4729 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4730 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4731 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4732 static regexp_t
4733 transform_3 (regexp_t regexp)
4735 if (regexp->mode == rm_sequence)
4737 regexp_t oneof = NULL;
4738 int oneof_index = 0;
4739 regexp_t result;
4740 regexp_t sequence;
4741 int i, j;
4743 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4744 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4746 oneof_index = i;
4747 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4748 break;
4750 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4752 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4753 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4754 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4755 + sizeof (regexp_t)
4756 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4757 result->mode = rm_oneof;
4758 result->pos = regexp->pos;
4759 REGEXP_ONEOF (result)->regexps_num
4760 = REGEXP_ONEOF (oneof)->regexps_num;
4761 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4763 sequence
4764 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4765 + sizeof (regexp_t)
4766 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4767 sequence->mode = rm_sequence;
4768 sequence->pos = regexp->pos;
4769 REGEXP_SEQUENCE (sequence)->regexps_num
4770 = REGEXP_SEQUENCE (regexp)->regexps_num;
4771 REGEXP_ONEOF (result)->regexps [i] = sequence;
4772 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4773 if (j != oneof_index)
4774 REGEXP_SEQUENCE (sequence)->regexps [j]
4775 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4776 else
4777 REGEXP_SEQUENCE (sequence)->regexps [j]
4778 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4780 regexp_transformed_p = 1;
4781 regexp = result;
4784 else if (regexp->mode == rm_allof)
4786 regexp_t oneof = NULL;
4787 regexp_t seq;
4788 int oneof_index = 0;
4789 int max_seq_length, allof_length;
4790 regexp_t result;
4791 regexp_t allof = NULL;
4792 regexp_t allof_op = NULL;
4793 int i, j;
4795 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4796 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4798 oneof_index = i;
4799 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4800 break;
4802 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4804 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4805 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4806 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4807 + sizeof (regexp_t)
4808 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4809 result->mode = rm_oneof;
4810 result->pos = regexp->pos;
4811 REGEXP_ONEOF (result)->regexps_num
4812 = REGEXP_ONEOF (oneof)->regexps_num;
4813 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4815 allof
4816 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4817 + sizeof (regexp_t)
4818 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4819 allof->mode = rm_allof;
4820 allof->pos = regexp->pos;
4821 REGEXP_ALLOF (allof)->regexps_num
4822 = REGEXP_ALLOF (regexp)->regexps_num;
4823 REGEXP_ONEOF (result)->regexps [i] = allof;
4824 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4825 if (j != oneof_index)
4826 REGEXP_ALLOF (allof)->regexps [j]
4827 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4828 else
4829 REGEXP_ALLOF (allof)->regexps [j]
4830 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4832 regexp_transformed_p = 1;
4833 regexp = result;
4835 max_seq_length = 0;
4836 if (regexp->mode == rm_allof)
4837 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4839 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4841 case rm_sequence:
4842 seq = REGEXP_ALLOF (regexp)->regexps [i];
4843 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4844 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4845 break;
4847 case rm_unit:
4848 case rm_nothing:
4849 break;
4851 default:
4852 max_seq_length = 0;
4853 goto break_for;
4856 break_for:
4857 if (max_seq_length != 0)
4859 gcc_assert (max_seq_length != 1
4860 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4861 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4862 + sizeof (regexp_t) * (max_seq_length - 1));
4863 result->mode = rm_sequence;
4864 result->pos = regexp->pos;
4865 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4866 for (i = 0; i < max_seq_length; i++)
4868 allof_length = 0;
4869 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4870 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4872 case rm_sequence:
4873 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4874 ->regexps [j])->regexps_num))
4876 allof_op
4877 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4878 ->regexps [j])
4879 ->regexps [i]);
4880 allof_length++;
4882 break;
4883 case rm_unit:
4884 case rm_nothing:
4885 if (i == 0)
4887 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4888 allof_length++;
4890 break;
4891 default:
4892 break;
4895 if (allof_length == 1)
4896 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4897 else
4899 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4900 + sizeof (regexp_t)
4901 * (allof_length - 1));
4902 allof->mode = rm_allof;
4903 allof->pos = regexp->pos;
4904 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4905 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4906 allof_length = 0;
4907 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4908 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4909 && (i <
4910 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4911 ->regexps [j])->regexps_num)))
4913 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4914 ->regexps [j])
4915 ->regexps [i]);
4916 REGEXP_ALLOF (allof)->regexps [allof_length]
4917 = allof_op;
4918 allof_length++;
4920 else if (i == 0
4921 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4922 == rm_unit
4923 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4924 == rm_nothing)))
4926 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4927 REGEXP_ALLOF (allof)->regexps [allof_length]
4928 = allof_op;
4929 allof_length++;
4933 regexp_transformed_p = 1;
4934 regexp = result;
4937 return regexp;
4940 /* The function traverses IR of reservation and applies transformations
4941 implemented by FUNC. */
4942 static regexp_t
4943 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4945 int i;
4947 switch (regexp->mode)
4949 case rm_sequence:
4950 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4951 REGEXP_SEQUENCE (regexp)->regexps [i]
4952 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4953 func);
4954 break;
4956 case rm_allof:
4957 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4958 REGEXP_ALLOF (regexp)->regexps [i]
4959 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4960 break;
4962 case rm_oneof:
4963 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4964 REGEXP_ONEOF (regexp)->regexps [i]
4965 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4966 break;
4968 case rm_repeat:
4969 REGEXP_REPEAT (regexp)->regexp
4970 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4971 break;
4973 case rm_nothing:
4974 case rm_unit:
4975 break;
4977 default:
4978 gcc_unreachable ();
4980 return (*func) (regexp);
4983 /* The function applies all transformations for IR representation of
4984 reservation REGEXP. */
4985 static regexp_t
4986 transform_regexp (regexp_t regexp)
4988 regexp = regexp_transform_func (regexp, transform_1);
4991 regexp_transformed_p = 0;
4992 regexp = regexp_transform_func (regexp, transform_2);
4993 regexp = regexp_transform_func (regexp, transform_3);
4995 while (regexp_transformed_p);
4996 return regexp;
4999 /* The function applies all transformations for reservations of all
5000 insn declarations. */
5001 static void
5002 transform_insn_regexps (void)
5004 decl_t decl;
5005 int i;
5007 transform_time = create_ticker ();
5008 add_advance_cycle_insn_decl ();
5009 if (collapse_flag)
5010 add_collapse_ndfa_insn_decl ();
5011 if (progress_flag)
5012 fprintf (stderr, "Reservation transformation...");
5013 for (i = 0; i < description->normal_decls_num; i++)
5015 decl = description->decls [i];
5016 if (decl->mode == dm_insn_reserv)
5017 DECL_INSN_RESERV (decl)->transformed_regexp
5018 = transform_regexp (copy_insn_regexp
5019 (DECL_INSN_RESERV (decl)->regexp));
5021 if (progress_flag)
5022 fprintf (stderr, "done\n");
5023 ticker_off (&transform_time);
5028 /* The following variable value is TRUE if the first annotated message
5029 about units to automata distribution has been output. */
5030 static int annotation_message_reported_p;
5032 /* The vector contains all decls which are automata. */
5033 static VEC(decl_t, heap) *automaton_decls;
5035 /* The following structure describes usage of a unit in a reservation. */
5036 struct unit_usage
5038 unit_decl_t unit_decl;
5039 /* The following forms a list of units used on the same cycle in the
5040 same alternative. The list is ordered by the correspdoning unit
5041 declarations and there is no unit declaration duplication in the
5042 list. */
5043 struct unit_usage *next;
5045 typedef struct unit_usage *unit_usage_t;
5047 DEF_VEC_P(unit_usage_t);
5048 DEF_VEC_ALLOC_P(unit_usage_t, heap);
5050 /* Obstack for unit_usage structures. */
5051 static struct obstack unit_usages;
5053 /* VLA for representation of array of pointers to unit usage
5054 structures. There is an element for each combination of
5055 (alternative number, cycle). Unit usages on given cycle in
5056 alternative with given number are referred through element with
5057 index equals to the cycle * number of all alternatives in the
5058 regexp + the alternative number. */
5059 static VEC(unit_usage_t, heap) *cycle_alt_unit_usages;
5061 /* The following function creates the structure unit_usage for UNIT on
5062 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
5063 accessed through cycle_alt_unit_usages. */
5064 static void
5065 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
5066 int alt_num)
5068 size_t length;
5069 unit_decl_t unit_decl;
5070 unit_usage_t unit_usage_ptr, curr, prev;
5071 int index;
5073 gcc_assert (regexp && regexp->mode == rm_oneof
5074 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
5075 unit_decl = REGEXP_UNIT (unit)->unit_decl;
5077 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
5078 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
5079 VEC_safe_push (unit_usage_t, heap, cycle_alt_unit_usages,
5080 (unit_usage_t) NULL);
5082 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5083 prev = NULL;
5084 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
5085 curr != NULL;
5086 prev = curr, curr = curr->next)
5087 if (curr->unit_decl >= unit_decl)
5088 break;
5089 if (curr != NULL && curr->unit_decl == unit_decl)
5090 return;
5091 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5092 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5093 obstack_finish (&unit_usages);
5094 unit_usage_ptr->unit_decl = unit_decl;
5095 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5096 unit_usage_ptr->next = curr;
5097 if (prev == NULL)
5098 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
5099 else
5100 prev->next = unit_usage_ptr;
5103 /* Return true if unit UNIT_DECL is present on the LIST. */
5104 static bool
5105 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5107 while (list != NULL)
5109 if (list->unit_decl == unit_decl)
5110 return true;
5111 list = list->next;
5113 return false;
5116 /* The function returns true if reservations of alternatives ALT1 and
5117 ALT2 are equal after excluding reservations of units of
5118 EXCLUDED_AUTOMATON_DECL. */
5119 static bool
5120 equal_alternatives_p (int alt1, int alt2, int n_alts,
5121 struct automaton_decl *excluded_automaton_decl)
5123 int i;
5124 unit_usage_t list1, list2;
5126 for (i = 0;
5127 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5128 i += n_alts)
5130 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5131 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5132 list1 = list1->next, list2 = list2->next)
5134 while (list1 != NULL
5135 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5136 list1 = list1->next;
5137 while (list2 != NULL
5138 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5139 list2 = list2->next;
5140 if (list1 == NULL || list2 == NULL)
5142 if (list1 != list2)
5143 return false;
5144 else
5145 break;
5147 if (list1->unit_decl != list2->unit_decl)
5148 return false;
5151 return true;
5154 DEF_VEC_I(int);
5155 DEF_VEC_ALLOC_I(int, heap);
5157 /* The function processes given REGEXP to find units with the wrong
5158 distribution. */
5159 static void
5160 check_regexp_units_distribution (const char *insn_reserv_name,
5161 regexp_t regexp)
5163 int i, j, k, cycle, start, n_alts, alt, alt2;
5164 bool annotation_reservation_message_reported_p;
5165 regexp_t seq, allof, unit;
5166 struct unit_usage *unit_usage_ptr;
5167 VEC(int, heap) *marked;
5169 if (regexp == NULL || regexp->mode != rm_oneof)
5170 return;
5171 /* Store all unit usages in the regexp: */
5172 obstack_init (&unit_usages);
5173 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5175 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5177 seq = REGEXP_ONEOF (regexp)->regexps [i];
5178 switch (seq->mode)
5180 case rm_sequence:
5181 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5183 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5184 switch (allof->mode)
5186 case rm_allof:
5187 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5189 unit = REGEXP_ALLOF (allof)->regexps [k];
5190 if (unit->mode == rm_unit)
5191 store_alt_unit_usage (regexp, unit, j, i);
5192 else
5193 gcc_assert (unit->mode == rm_nothing);
5195 break;
5197 case rm_unit:
5198 store_alt_unit_usage (regexp, allof, j, i);
5199 break;
5201 case rm_nothing:
5202 break;
5204 default:
5205 gcc_unreachable ();
5208 break;
5210 case rm_allof:
5211 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5213 unit = REGEXP_ALLOF (seq)->regexps [k];
5214 switch (unit->mode)
5216 case rm_unit:
5217 store_alt_unit_usage (regexp, unit, 0, i);
5218 break;
5220 case rm_nothing:
5221 break;
5223 default:
5224 gcc_unreachable ();
5227 break;
5229 case rm_unit:
5230 store_alt_unit_usage (regexp, seq, 0, i);
5231 break;
5233 case rm_nothing:
5234 break;
5236 default:
5237 gcc_unreachable ();
5240 /* Check distribution: */
5241 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5242 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5243 unit_usage_ptr != NULL;
5244 unit_usage_ptr = unit_usage_ptr->next)
5245 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5246 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5247 marked = VEC_alloc (int, heap, n_alts);
5248 for (i = 0; i < n_alts; i++)
5249 VEC_safe_push (int, heap, marked, 0);
5250 annotation_reservation_message_reported_p = false;
5251 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5253 cycle = i / n_alts;
5254 start = cycle * n_alts;
5255 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5256 unit_usage_ptr != NULL;
5257 unit_usage_ptr = unit_usage_ptr->next)
5259 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5260 continue;
5261 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5262 for (alt = 0; alt < n_alts; alt++)
5263 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5264 cycle_alt_unit_usages,
5265 start + alt),
5266 unit_usage_ptr->unit_decl))
5267 break;
5268 if (alt >= n_alts)
5269 continue;
5270 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5271 for (alt = 0; alt < n_alts; alt++)
5273 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5274 cycle_alt_unit_usages,
5275 start + alt),
5276 unit_usage_ptr->unit_decl))
5277 continue;
5278 for (j = 0;
5279 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5280 j++)
5282 alt2 = j % n_alts;
5283 if (! unit_present_on_list_p
5284 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5285 start + alt2),
5286 unit_usage_ptr->unit_decl)
5287 && equal_alternatives_p (alt, alt2, n_alts,
5288 unit_usage_ptr
5289 ->unit_decl->automaton_decl))
5291 VEC_replace (int, marked, alt, 1);
5292 VEC_replace (int, marked, alt2, 1);
5296 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5298 if (alt < n_alts && 0)
5300 if (! annotation_message_reported_p)
5302 fprintf (stderr, "\n");
5303 error ("The following units do not satisfy units-automata distribution rule");
5304 error ("(Unit presence on one alt and its absence on other alt\n");
5305 error (" result in different other automata reservations)");
5306 annotation_message_reported_p = TRUE;
5308 if (! annotation_reservation_message_reported_p)
5310 error ("Reserv %s:", insn_reserv_name);
5311 annotation_reservation_message_reported_p = true;
5313 error (" Unit %s, cycle %d, alt %d, another alt %d",
5314 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5318 VEC_free (int, heap, marked);
5319 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5320 obstack_free (&unit_usages, NULL);
5323 /* The function finds units which violates units to automata
5324 distribution rule. If the units exist, report about them. */
5325 static void
5326 check_unit_distributions_to_automata (void)
5328 decl_t decl;
5329 int i;
5331 if (progress_flag)
5332 fprintf (stderr, "Check unit distributions to automata...");
5333 automaton_decls = NULL;
5334 for (i = 0; i < description->decls_num; i++)
5336 decl = description->decls [i];
5337 if (decl->mode == dm_automaton)
5338 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5340 if (VEC_length (decl_t, automaton_decls) > 1)
5342 annotation_message_reported_p = FALSE;
5343 for (i = 0; i < description->decls_num; i++)
5345 decl = description->decls [i];
5346 if (decl->mode == dm_insn_reserv)
5347 check_regexp_units_distribution
5348 (DECL_INSN_RESERV (decl)->name,
5349 DECL_INSN_RESERV (decl)->transformed_regexp);
5352 VEC_free (decl_t, heap, automaton_decls);
5353 if (progress_flag)
5354 fprintf (stderr, "done\n");
5359 /* The page contains code for building alt_states (see comments for
5360 IR) describing all possible insns reservations of an automaton. */
5362 /* Current state being formed for which the current alt_state
5363 refers. */
5364 static state_t state_being_formed;
5366 /* Current alt_state being formed. */
5367 static alt_state_t alt_state_being_formed;
5369 /* This recursive function processes `,' and units in reservation
5370 REGEXP for forming alt_states of AUTOMATON. It is believed that
5371 CURR_CYCLE is start cycle of all reservation REGEXP. */
5372 static int
5373 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5374 int curr_cycle)
5376 int i;
5378 if (regexp == NULL)
5379 return curr_cycle;
5381 switch (regexp->mode)
5383 case rm_unit:
5384 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5385 == automaton->automaton_order_num)
5386 set_state_reserv (state_being_formed, curr_cycle,
5387 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5388 return curr_cycle;
5390 case rm_sequence:
5391 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5392 curr_cycle
5393 = process_seq_for_forming_states
5394 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5395 return curr_cycle;
5397 case rm_allof:
5399 int finish_cycle = 0;
5400 int cycle;
5402 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5404 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5405 ->regexps [i],
5406 automaton, curr_cycle);
5407 if (finish_cycle < cycle)
5408 finish_cycle = cycle;
5410 return finish_cycle;
5413 case rm_nothing:
5414 return curr_cycle;
5416 default:
5417 gcc_unreachable ();
5421 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5422 inserts alt_state into the table. */
5423 static void
5424 finish_forming_alt_state (alt_state_t alt_state,
5425 automaton_t automaton ATTRIBUTE_UNUSED)
5427 state_t state_in_table;
5428 state_t corresponding_state;
5430 corresponding_state = alt_state->state;
5431 state_in_table = insert_state (corresponding_state);
5432 if (state_in_table != corresponding_state)
5434 free_state (corresponding_state);
5435 alt_state->state = state_in_table;
5439 /* The following variable value is current automaton insn for whose
5440 reservation the alt states are created. */
5441 static ainsn_t curr_ainsn;
5443 /* This recursive function processes `|' in reservation REGEXP for
5444 forming alt_states of AUTOMATON. List of the alt states should
5445 have the same order as in the description. */
5446 static void
5447 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5448 int inside_oneof_p)
5450 int i;
5452 if (regexp->mode != rm_oneof)
5454 alt_state_being_formed = get_free_alt_state ();
5455 state_being_formed = get_free_state (1, automaton);
5456 alt_state_being_formed->state = state_being_formed;
5457 /* We inserts in reverse order but we process alternatives also
5458 in reverse order. So we have the same order of alternative
5459 as in the description. */
5460 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5461 curr_ainsn->alt_states = alt_state_being_formed;
5462 (void) process_seq_for_forming_states (regexp, automaton, 0);
5463 finish_forming_alt_state (alt_state_being_formed, automaton);
5465 else
5467 gcc_assert (!inside_oneof_p);
5468 /* We processes it in reverse order to get list with the same
5469 order as in the description. See also the previous
5470 commentary. */
5471 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5472 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5473 automaton, 1);
5477 /* Create nodes alt_state for all AUTOMATON insns. */
5478 static void
5479 create_alt_states (automaton_t automaton)
5481 struct insn_reserv_decl *reserv_decl;
5483 for (curr_ainsn = automaton->ainsn_list;
5484 curr_ainsn != NULL;
5485 curr_ainsn = curr_ainsn->next_ainsn)
5487 reserv_decl = curr_ainsn->insn_reserv_decl;
5488 if (!special_decl_p (reserv_decl))
5490 curr_ainsn->alt_states = NULL;
5491 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5492 automaton, 0);
5493 curr_ainsn->sorted_alt_states
5494 = uniq_sort_alt_states (curr_ainsn->alt_states);
5501 /* The page contains major code for building DFA(s) for fast pipeline
5502 hazards recognition. */
5504 /* The function forms list of ainsns of AUTOMATON with the same
5505 reservation. */
5507 static void
5508 form_ainsn_with_same_reservs (automaton_t automaton)
5510 ainsn_t curr_ainsn;
5511 size_t i;
5512 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5514 for (curr_ainsn = automaton->ainsn_list;
5515 curr_ainsn != NULL;
5516 curr_ainsn = curr_ainsn->next_ainsn)
5517 if (special_decl_p (curr_ainsn->insn_reserv_decl))
5519 curr_ainsn->next_same_reservs_insn = NULL;
5520 curr_ainsn->first_insn_with_same_reservs = 1;
5522 else
5524 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5525 if (alt_states_eq
5526 (curr_ainsn->sorted_alt_states,
5527 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5528 break;
5529 curr_ainsn->next_same_reservs_insn = NULL;
5530 if (i < VEC_length (ainsn_t, last_insns))
5532 curr_ainsn->first_insn_with_same_reservs = 0;
5533 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5534 = curr_ainsn;
5535 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5537 else
5539 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5540 curr_ainsn->first_insn_with_same_reservs = 1;
5543 VEC_free (ainsn_t, heap, last_insns);
5546 /* Forming unit reservations which can affect creating the automaton
5547 states achieved from a given state. It permits to build smaller
5548 automata in many cases. We would have the same automata after
5549 the minimization without such optimization, but the automaton
5550 right after the building could be huge. So in other words, usage
5551 of reservs_matter means some minimization during building the
5552 automaton. */
5553 static reserv_sets_t
5554 form_reservs_matter (automaton_t automaton)
5556 int cycle, unit;
5557 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5559 for (cycle = 0; cycle < max_cycles_num; cycle++)
5560 for (unit = 0; unit < description->units_num; unit++)
5561 if (units_array [unit]->automaton_decl
5562 == automaton->corresponding_automaton_decl
5563 && (cycle >= units_array [unit]->min_occ_cycle_num
5564 /* We can not remove queried unit from reservations. */
5565 || units_array [unit]->query_p
5566 /* We can not remove units which are used
5567 `exclusion_set', `presence_set',
5568 `final_presence_set', `absence_set', and
5569 `final_absence_set'. */
5570 || units_array [unit]->in_set_p))
5571 set_unit_reserv (reservs_matter, cycle, unit);
5572 return reservs_matter;
5575 /* The following function creates all states of nondeterministic AUTOMATON. */
5576 static void
5577 make_automaton (automaton_t automaton)
5579 ainsn_t ainsn;
5580 struct insn_reserv_decl *insn_reserv_decl;
5581 alt_state_t alt_state;
5582 state_t state;
5583 state_t start_state;
5584 state_t state2;
5585 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5586 int states_n;
5587 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5589 /* Create the start state (empty state). */
5590 start_state = insert_state (get_free_state (1, automaton));
5591 automaton->start_state = start_state;
5592 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5593 VEC_safe_push (state_t, heap, state_stack, start_state);
5594 states_n = 1;
5595 while (VEC_length (state_t, state_stack) != 0)
5597 state = VEC_pop (state_t, state_stack);
5598 for (ainsn = automaton->ainsn_list;
5599 ainsn != NULL;
5600 ainsn = ainsn->next_ainsn)
5601 if (ainsn->first_insn_with_same_reservs)
5603 insn_reserv_decl = ainsn->insn_reserv_decl;
5604 if (!special_decl_p (insn_reserv_decl))
5606 /* We process alt_states in the same order as they are
5607 present in the description. */
5608 for (alt_state = ainsn->alt_states;
5609 alt_state != NULL;
5610 alt_state = alt_state->next_alt_state)
5612 state2 = alt_state->state;
5613 if (!intersected_state_reservs_p (state, state2))
5615 state2 = states_union (state, state2, reservs_matter);
5616 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5618 state2->it_was_placed_in_stack_for_NDFA_forming
5619 = 1;
5620 VEC_safe_push (state_t, heap, state_stack, state2);
5621 states_n++;
5622 if (progress_flag && states_n % 100 == 0)
5623 fprintf (stderr, ".");
5625 add_arc (state, state2, ainsn);
5626 if (!ndfa_flag)
5627 break;
5632 /* Add transition to advance cycle. */
5633 state2 = state_shift (state, reservs_matter);
5634 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5636 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5637 VEC_safe_push (state_t, heap, state_stack, state2);
5638 states_n++;
5639 if (progress_flag && states_n % 100 == 0)
5640 fprintf (stderr, ".");
5642 add_arc (state, state2, automaton->advance_ainsn);
5644 VEC_free (state_t, heap, state_stack);
5647 /* Form lists of all arcs of STATE marked by the same ainsn. */
5648 static void
5649 form_arcs_marked_by_insn (state_t state)
5651 decl_t decl;
5652 arc_t arc;
5653 int i;
5655 for (i = 0; i < description->decls_num; i++)
5657 decl = description->decls [i];
5658 if (decl->mode == dm_insn_reserv)
5659 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5661 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5663 gcc_assert (arc->insn);
5664 arc->next_arc_marked_by_insn
5665 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5666 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5670 /* The function creates composed state (see comments for IR) from
5671 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5672 same insn. If the composed state is not in STATE_STACK yet, it is
5673 pushed into STATE_STACK. */
5675 static int
5676 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5677 VEC(state_t, heap) **state_stack)
5679 state_t state;
5680 alt_state_t alt_state, curr_alt_state;
5681 alt_state_t new_alt_state;
5682 arc_t curr_arc;
5683 arc_t next_arc;
5684 state_t state_in_table;
5685 state_t temp_state;
5686 alt_state_t canonical_alt_states_list;
5687 int alts_number;
5688 int new_state_p = 0;
5690 if (arcs_marked_by_insn == NULL)
5691 return new_state_p;
5692 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5693 state = arcs_marked_by_insn->to_state;
5694 else
5696 gcc_assert (ndfa_flag);
5697 /* Create composed state. */
5698 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5699 curr_alt_state = NULL;
5700 for (curr_arc = arcs_marked_by_insn;
5701 curr_arc != NULL;
5702 curr_arc = curr_arc->next_arc_marked_by_insn)
5703 if (curr_arc->to_state->component_states == NULL)
5705 new_alt_state = get_free_alt_state ();
5706 new_alt_state->next_alt_state = curr_alt_state;
5707 new_alt_state->state = curr_arc->to_state;
5708 curr_alt_state = new_alt_state;
5710 else
5711 for (alt_state = curr_arc->to_state->component_states;
5712 alt_state != NULL;
5713 alt_state = alt_state->next_sorted_alt_state)
5715 new_alt_state = get_free_alt_state ();
5716 new_alt_state->next_alt_state = curr_alt_state;
5717 new_alt_state->state = alt_state->state;
5718 gcc_assert (!alt_state->state->component_states);
5719 curr_alt_state = new_alt_state;
5721 /* There are not identical sets in the alt state list. */
5722 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5723 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5725 temp_state = state;
5726 state = canonical_alt_states_list->state;
5727 free_state (temp_state);
5729 else
5731 state->component_states = canonical_alt_states_list;
5732 state_in_table = insert_state (state);
5733 if (state_in_table != state)
5735 gcc_assert
5736 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5737 free_state (state);
5738 state = state_in_table;
5740 else
5742 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5743 new_state_p = 1;
5744 for (curr_alt_state = state->component_states;
5745 curr_alt_state != NULL;
5746 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5747 for (curr_arc = first_out_arc (curr_alt_state->state);
5748 curr_arc != NULL;
5749 curr_arc = next_out_arc (curr_arc))
5750 if (!collapse_flag
5751 /* When producing collapse-NDFA transitions, we
5752 only add advance-cycle transitions to the
5753 collapsed states. */
5754 || (curr_arc->insn->insn_reserv_decl
5755 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
5756 add_arc (state, curr_arc->to_state, curr_arc->insn);
5758 arcs_marked_by_insn->to_state = state;
5759 for (alts_number = 0,
5760 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5761 curr_arc != NULL;
5762 curr_arc = next_arc)
5764 next_arc = curr_arc->next_arc_marked_by_insn;
5765 remove_arc (original_state, curr_arc);
5766 alts_number++;
5770 if (!state->it_was_placed_in_stack_for_DFA_forming)
5772 state->it_was_placed_in_stack_for_DFA_forming = 1;
5773 VEC_safe_push (state_t, heap, *state_stack, state);
5775 return new_state_p;
5778 /* The function transforms nondeterministic AUTOMATON into
5779 deterministic. */
5781 static void
5782 NDFA_to_DFA (automaton_t automaton)
5784 state_t start_state;
5785 state_t state;
5786 decl_t decl;
5787 VEC(state_t, heap) *state_stack;
5788 int i;
5789 int states_n;
5791 state_stack = VEC_alloc (state_t, heap, 0);
5793 /* Create the start state (empty state). */
5794 start_state = automaton->start_state;
5795 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5796 VEC_safe_push (state_t, heap, state_stack, start_state);
5797 states_n = 1;
5798 while (VEC_length (state_t, state_stack) != 0)
5800 state = VEC_pop (state_t, state_stack);
5801 form_arcs_marked_by_insn (state);
5802 for (i = 0; i < description->decls_num; i++)
5804 decl = description->decls [i];
5805 if (decl->mode == dm_insn_reserv
5806 && decl != collapse_ndfa_insn_decl
5807 && create_composed_state
5808 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5809 &state_stack))
5811 states_n++;
5812 if (progress_flag && states_n % 100 == 0)
5813 fprintf (stderr, ".");
5816 /* Add a transition to collapse the NDFA. */
5817 if (collapse_flag)
5819 if (state->component_states != NULL)
5821 state_t state2 = state->component_states->state;
5822 if (!state2->it_was_placed_in_stack_for_DFA_forming)
5824 state2->it_was_placed_in_stack_for_DFA_forming = 1;
5825 VEC_safe_push (state_t, heap, state_stack, state2);
5827 add_arc (state, state2, automaton->collapse_ainsn);
5829 else
5830 add_arc (state, state, automaton->collapse_ainsn);
5833 VEC_free (state_t, heap, state_stack);
5836 /* The following variable value is current number (1, 2, ...) of passing
5837 graph of states. */
5838 static int curr_state_graph_pass_num;
5840 /* This recursive function passes all states achieved from START_STATE
5841 and applies APPLIED_FUNC to them. */
5842 static void
5843 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5845 arc_t arc;
5847 if (start_state->pass_num == curr_state_graph_pass_num)
5848 return;
5849 start_state->pass_num = curr_state_graph_pass_num;
5850 (*applied_func) (start_state);
5851 for (arc = first_out_arc (start_state);
5852 arc != NULL;
5853 arc = next_out_arc (arc))
5854 pass_state_graph (arc->to_state, applied_func);
5857 /* This recursive function passes all states of AUTOMATON and applies
5858 APPLIED_FUNC to them. */
5859 static void
5860 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5862 curr_state_graph_pass_num++;
5863 pass_state_graph (automaton->start_state, applied_func);
5866 /* The function initializes code for passing of all states. */
5867 static void
5868 initiate_pass_states (void)
5870 curr_state_graph_pass_num = 0;
5873 /* The following vla is used for storing pointers to all achieved
5874 states. */
5875 static VEC(state_t, heap) *all_achieved_states;
5877 /* This function is called by function pass_states to add an achieved
5878 STATE. */
5879 static void
5880 add_achieved_state (state_t state)
5882 VEC_safe_push (state_t, heap, all_achieved_states, state);
5885 /* The function sets up equivalence numbers of insns which mark all
5886 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5887 nonzero value) or by equiv_class_num_2 of the destination state. */
5888 static void
5889 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5891 arc_t arc;
5893 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5895 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5896 arc->insn->insn_reserv_decl->equiv_class_num
5897 = (odd_iteration_flag
5898 ? arc->to_state->equiv_class_num_1
5899 : arc->to_state->equiv_class_num_2);
5900 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5904 /* The function clears equivalence numbers and alt_states in all insns
5905 which mark all out arcs of STATE. */
5906 static void
5907 clear_arc_insns_equiv_num (state_t state)
5909 arc_t arc;
5911 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5912 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5916 /* The following function returns TRUE if STATE reserves the unit with
5917 UNIT_NUM on the first cycle. */
5918 static int
5919 first_cycle_unit_presence (state_t state, int unit_num)
5921 alt_state_t alt_state;
5923 if (state->component_states == NULL)
5924 return test_unit_reserv (state->reservs, 0, unit_num);
5925 else
5927 for (alt_state = state->component_states;
5928 alt_state != NULL;
5929 alt_state = alt_state->next_sorted_alt_state)
5930 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5931 return true;
5933 return false;
5936 /* This fills in the presence_signature[] member of STATE. */
5937 static void
5938 cache_presence (state_t state)
5940 int i, num = 0;
5941 unsigned int sz;
5942 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5943 / (sizeof (int) * CHAR_BIT);
5945 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5946 for (i = 0; i < description->units_num; i++)
5947 if (units_array [i]->query_p)
5949 int presence1_p = first_cycle_unit_presence (state, i);
5950 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5951 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5952 num++;
5956 /* The function returns nonzero value if STATE is not equivalent to
5957 ANOTHER_STATE from the same current partition on equivalence
5958 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5959 output arcs. Iteration of making equivalence partition is defined
5960 by ODD_ITERATION_FLAG. */
5961 static int
5962 state_is_differed (state_t state, state_t another_state,
5963 int odd_iteration_flag)
5965 arc_t arc;
5966 unsigned int sz, si;
5968 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5970 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5971 / (sizeof (int) * CHAR_BIT);
5973 for (si = 0; si < sz; si++)
5974 gcc_assert (state->presence_signature[si]
5975 == another_state->presence_signature[si]);
5977 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5979 if ((odd_iteration_flag
5980 ? arc->to_state->equiv_class_num_1
5981 : arc->to_state->equiv_class_num_2)
5982 != arc->insn->insn_reserv_decl->equiv_class_num)
5983 return 1;
5986 return 0;
5989 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5990 and return -1, 0 or 1. This function can be used as predicate for
5991 qsort(). It requires the member presence_signature[] of both
5992 states be filled. */
5993 static int
5994 compare_states_for_equiv (const void *state_ptr_1,
5995 const void *state_ptr_2)
5997 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5998 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5999 unsigned int sz, si;
6000 if (s1->num_out_arcs < s2->num_out_arcs)
6001 return -1;
6002 else if (s1->num_out_arcs > s2->num_out_arcs)
6003 return 1;
6005 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
6006 / (sizeof (int) * CHAR_BIT);
6008 for (si = 0; si < sz; si++)
6009 if (s1->presence_signature[si] < s2->presence_signature[si])
6010 return -1;
6011 else if (s1->presence_signature[si] > s2->presence_signature[si])
6012 return 1;
6013 return 0;
6016 /* The function makes initial partition of STATES on equivalent
6017 classes and saves it into *CLASSES. This function requires the input
6018 to be sorted via compare_states_for_equiv(). */
6019 static int
6020 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
6022 size_t i;
6023 state_t prev = 0;
6024 int class_num = 1;
6026 *classes = VEC_alloc (state_t, heap, 150);
6027 for (i = 0; i < VEC_length (state_t, states); i++)
6029 state_t state = VEC_index (state_t, states, i);
6030 if (prev)
6032 if (compare_states_for_equiv (&prev, &state) != 0)
6034 VEC_safe_push (state_t, heap, *classes, prev);
6035 class_num++;
6036 prev = NULL;
6039 state->equiv_class_num_1 = class_num;
6040 state->next_equiv_class_state = prev;
6041 prev = state;
6043 if (prev)
6044 VEC_safe_push (state_t, heap, *classes, prev);
6045 return class_num;
6048 /* The function copies pointers to equivalent states from vla FROM
6049 into vla TO. */
6050 static void
6051 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
6053 VEC_free (state_t, heap, *to);
6054 *to = VEC_copy (state_t, heap, from);
6057 /* The function processes equivalence class given by its first state,
6058 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6059 are not equivalent states, the function partitions the class
6060 removing nonequivalent states and placing them in
6061 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6062 assigns it to the state equivalence number. If the class has been
6063 partitioned, the function returns nonzero value. */
6064 static int
6065 partition_equiv_class (state_t first_state, int odd_iteration_flag,
6066 VEC(state_t, heap) **next_iteration_classes,
6067 int *new_equiv_class_num_ptr)
6069 state_t new_equiv_class;
6070 int partition_p;
6071 state_t curr_state;
6072 state_t prev_state;
6073 state_t next_state;
6075 partition_p = 0;
6077 while (first_state != NULL)
6079 new_equiv_class = NULL;
6080 if (first_state->next_equiv_class_state != NULL)
6082 /* There are more one states in the class equivalence. */
6083 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6084 for (prev_state = first_state,
6085 curr_state = first_state->next_equiv_class_state;
6086 curr_state != NULL;
6087 curr_state = next_state)
6089 next_state = curr_state->next_equiv_class_state;
6090 if (state_is_differed (curr_state, first_state,
6091 odd_iteration_flag))
6093 /* Remove curr state from the class equivalence. */
6094 prev_state->next_equiv_class_state = next_state;
6095 /* Add curr state to the new class equivalence. */
6096 curr_state->next_equiv_class_state = new_equiv_class;
6097 if (new_equiv_class == NULL)
6098 (*new_equiv_class_num_ptr)++;
6099 if (odd_iteration_flag)
6100 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6101 else
6102 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6103 new_equiv_class = curr_state;
6104 partition_p = 1;
6106 else
6107 prev_state = curr_state;
6109 clear_arc_insns_equiv_num (first_state);
6111 if (new_equiv_class != NULL)
6112 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
6113 first_state = new_equiv_class;
6115 return partition_p;
6118 /* The function finds equivalent states of AUTOMATON. */
6119 static void
6120 evaluate_equiv_classes (automaton_t automaton,
6121 VEC(state_t, heap) **equiv_classes)
6123 int new_equiv_class_num;
6124 int odd_iteration_flag;
6125 int finish_flag;
6126 VEC (state_t, heap) *next_iteration_classes;
6127 size_t i;
6129 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6130 pass_states (automaton, add_achieved_state);
6131 pass_states (automaton, cache_presence);
6132 VEC_qsort (state_t, all_achieved_states, compare_states_for_equiv);
6134 odd_iteration_flag = 0;
6135 new_equiv_class_num = init_equiv_class (all_achieved_states,
6136 &next_iteration_classes);
6140 odd_iteration_flag = !odd_iteration_flag;
6141 finish_flag = 1;
6142 copy_equiv_class (equiv_classes, next_iteration_classes);
6144 /* Transfer equiv numbers for the next iteration. */
6145 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6146 if (odd_iteration_flag)
6147 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6148 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6149 else
6150 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6151 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6153 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6154 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6155 odd_iteration_flag,
6156 &next_iteration_classes,
6157 &new_equiv_class_num))
6158 finish_flag = 0;
6160 while (!finish_flag);
6161 VEC_free (state_t, heap, next_iteration_classes);
6162 VEC_free (state_t, heap, all_achieved_states);
6165 /* The function merges equivalent states of AUTOMATON. */
6166 static void
6167 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6169 state_t curr_state;
6170 state_t new_state;
6171 state_t first_class_state;
6172 alt_state_t alt_states;
6173 alt_state_t alt_state, new_alt_state;
6174 arc_t curr_arc;
6175 arc_t next_arc;
6176 size_t i;
6178 /* Create states corresponding to equivalence classes containing two
6179 or more states. */
6180 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6182 curr_state = VEC_index (state_t, equiv_classes, i);
6183 if (curr_state->next_equiv_class_state != NULL)
6185 /* There are more one states in the class equivalence. */
6186 /* Create new compound state. */
6187 new_state = get_free_state (0, automaton);
6188 alt_states = NULL;
6189 first_class_state = curr_state;
6190 for (curr_state = first_class_state;
6191 curr_state != NULL;
6192 curr_state = curr_state->next_equiv_class_state)
6194 curr_state->equiv_class_state = new_state;
6195 if (curr_state->component_states == NULL)
6197 new_alt_state = get_free_alt_state ();
6198 new_alt_state->state = curr_state;
6199 new_alt_state->next_alt_state = alt_states;
6200 alt_states = new_alt_state;
6202 else
6203 for (alt_state = curr_state->component_states;
6204 alt_state != NULL;
6205 alt_state = alt_state->next_sorted_alt_state)
6207 new_alt_state = get_free_alt_state ();
6208 new_alt_state->state = alt_state->state;
6209 new_alt_state->next_alt_state = alt_states;
6210 alt_states = new_alt_state;
6213 /* Its is important that alt states were sorted before and
6214 after merging to have the same querying results. */
6215 new_state->component_states = uniq_sort_alt_states (alt_states);
6217 else
6218 curr_state->equiv_class_state = curr_state;
6221 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6223 curr_state = VEC_index (state_t, equiv_classes, i);
6224 if (curr_state->next_equiv_class_state != NULL)
6226 first_class_state = curr_state;
6227 /* Create new arcs output from the state corresponding to
6228 equiv class. */
6229 for (curr_arc = first_out_arc (first_class_state);
6230 curr_arc != NULL;
6231 curr_arc = next_out_arc (curr_arc))
6232 add_arc (first_class_state->equiv_class_state,
6233 curr_arc->to_state->equiv_class_state,
6234 curr_arc->insn);
6235 /* Delete output arcs from states of given class equivalence. */
6236 for (curr_state = first_class_state;
6237 curr_state != NULL;
6238 curr_state = curr_state->next_equiv_class_state)
6240 if (automaton->start_state == curr_state)
6241 automaton->start_state = curr_state->equiv_class_state;
6242 /* Delete the state and its output arcs. */
6243 for (curr_arc = first_out_arc (curr_state);
6244 curr_arc != NULL;
6245 curr_arc = next_arc)
6247 next_arc = next_out_arc (curr_arc);
6248 free_arc (curr_arc);
6252 else
6254 /* Change `to_state' of arcs output from the state of given
6255 equivalence class. */
6256 for (curr_arc = first_out_arc (curr_state);
6257 curr_arc != NULL;
6258 curr_arc = next_out_arc (curr_arc))
6259 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6264 /* The function sets up new_cycle_p for states if there is arc to the
6265 state marked by advance_cycle_insn_decl. */
6266 static void
6267 set_new_cycle_flags (state_t state)
6269 arc_t arc;
6271 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6272 if (arc->insn->insn_reserv_decl
6273 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6274 arc->to_state->new_cycle_p = 1;
6277 /* The top level function for minimization of deterministic
6278 AUTOMATON. */
6279 static void
6280 minimize_DFA (automaton_t automaton)
6282 VEC(state_t, heap) *equiv_classes = 0;
6284 evaluate_equiv_classes (automaton, &equiv_classes);
6285 merge_states (automaton, equiv_classes);
6286 pass_states (automaton, set_new_cycle_flags);
6288 VEC_free (state_t, heap, equiv_classes);
6291 /* Values of two variables are counted number of states and arcs in an
6292 automaton. */
6293 static int curr_counted_states_num;
6294 static int curr_counted_arcs_num;
6296 /* The function is called by function `pass_states' to count states
6297 and arcs of an automaton. */
6298 static void
6299 incr_states_and_arcs_nums (state_t state)
6301 arc_t arc;
6303 curr_counted_states_num++;
6304 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6305 curr_counted_arcs_num++;
6308 /* The function counts states and arcs of AUTOMATON. */
6309 static void
6310 count_states_and_arcs (automaton_t automaton, int *states_num,
6311 int *arcs_num)
6313 curr_counted_states_num = 0;
6314 curr_counted_arcs_num = 0;
6315 pass_states (automaton, incr_states_and_arcs_nums);
6316 *states_num = curr_counted_states_num;
6317 *arcs_num = curr_counted_arcs_num;
6320 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6321 recognition after checking and simplifying IR of the
6322 description. */
6323 static void
6324 build_automaton (automaton_t automaton)
6326 int states_num;
6327 int arcs_num;
6329 ticker_on (&NDFA_time);
6330 if (progress_flag)
6332 if (automaton->corresponding_automaton_decl == NULL)
6333 fprintf (stderr, "Create anonymous automaton");
6334 else
6335 fprintf (stderr, "Create automaton `%s'",
6336 automaton->corresponding_automaton_decl->name);
6337 fprintf (stderr, " (1 dot is 100 new states):");
6339 make_automaton (automaton);
6340 if (progress_flag)
6341 fprintf (stderr, " done\n");
6342 ticker_off (&NDFA_time);
6343 count_states_and_arcs (automaton, &states_num, &arcs_num);
6344 automaton->NDFA_states_num = states_num;
6345 automaton->NDFA_arcs_num = arcs_num;
6346 ticker_on (&NDFA_to_DFA_time);
6347 if (progress_flag)
6349 if (automaton->corresponding_automaton_decl == NULL)
6350 fprintf (stderr, "Make anonymous DFA");
6351 else
6352 fprintf (stderr, "Make DFA `%s'",
6353 automaton->corresponding_automaton_decl->name);
6354 fprintf (stderr, " (1 dot is 100 new states):");
6356 NDFA_to_DFA (automaton);
6357 if (progress_flag)
6358 fprintf (stderr, " done\n");
6359 ticker_off (&NDFA_to_DFA_time);
6360 count_states_and_arcs (automaton, &states_num, &arcs_num);
6361 automaton->DFA_states_num = states_num;
6362 automaton->DFA_arcs_num = arcs_num;
6363 if (!no_minimization_flag)
6365 ticker_on (&minimize_time);
6366 if (progress_flag)
6368 if (automaton->corresponding_automaton_decl == NULL)
6369 fprintf (stderr, "Minimize anonymous DFA...");
6370 else
6371 fprintf (stderr, "Minimize DFA `%s'...",
6372 automaton->corresponding_automaton_decl->name);
6374 minimize_DFA (automaton);
6375 if (progress_flag)
6376 fprintf (stderr, "done\n");
6377 ticker_off (&minimize_time);
6378 count_states_and_arcs (automaton, &states_num, &arcs_num);
6379 automaton->minimal_DFA_states_num = states_num;
6380 automaton->minimal_DFA_arcs_num = arcs_num;
6386 /* The page contains code for enumeration of all states of an automaton. */
6388 /* Variable used for enumeration of all states of an automaton. Its
6389 value is current number of automaton states. */
6390 static int curr_state_order_num;
6392 /* The function is called by function `pass_states' for enumerating
6393 states. */
6394 static void
6395 set_order_state_num (state_t state)
6397 state->order_state_num = curr_state_order_num;
6398 curr_state_order_num++;
6401 /* The function enumerates all states of AUTOMATON. */
6402 static void
6403 enumerate_states (automaton_t automaton)
6405 curr_state_order_num = 0;
6406 pass_states (automaton, set_order_state_num);
6407 automaton->achieved_states_num = curr_state_order_num;
6412 /* The page contains code for finding equivalent automaton insns
6413 (ainsns). */
6415 /* The function inserts AINSN into cyclic list
6416 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6417 static ainsn_t
6418 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6419 ainsn_t cyclic_equiv_class_insn_list)
6421 if (cyclic_equiv_class_insn_list == NULL)
6422 ainsn->next_equiv_class_insn = ainsn;
6423 else
6425 ainsn->next_equiv_class_insn
6426 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6427 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6429 return ainsn;
6432 /* The function deletes equiv_class_insn into cyclic list of
6433 equivalent ainsns. */
6434 static void
6435 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6437 ainsn_t curr_equiv_class_insn;
6438 ainsn_t prev_equiv_class_insn;
6440 prev_equiv_class_insn = equiv_class_insn;
6441 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6442 curr_equiv_class_insn != equiv_class_insn;
6443 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6444 prev_equiv_class_insn = curr_equiv_class_insn;
6445 if (prev_equiv_class_insn != equiv_class_insn)
6446 prev_equiv_class_insn->next_equiv_class_insn
6447 = equiv_class_insn->next_equiv_class_insn;
6450 /* The function processes AINSN of a state in order to find equivalent
6451 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6452 state. */
6453 static void
6454 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6456 ainsn_t next_insn;
6457 ainsn_t curr_insn;
6458 ainsn_t cyclic_insn_list;
6459 arc_t arc;
6461 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6462 curr_insn = ainsn;
6463 /* New class of ainsns which are not equivalent to given ainsn. */
6464 cyclic_insn_list = NULL;
6467 next_insn = curr_insn->next_equiv_class_insn;
6468 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6469 if (arc == NULL
6470 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6471 != arc->to_state))
6473 delete_ainsn_from_equiv_class (curr_insn);
6474 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6475 cyclic_insn_list);
6477 curr_insn = next_insn;
6479 while (curr_insn != ainsn);
6482 /* The function processes STATE in order to find equivalent ainsns. */
6483 static void
6484 process_state_for_insn_equiv_partition (state_t state)
6486 arc_t arc;
6487 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6489 /* Process insns of the arcs. */
6490 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6491 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6492 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6493 process_insn_equiv_class (arc->insn, insn_arcs_array);
6495 free (insn_arcs_array);
6498 /* The function searches for equivalent ainsns of AUTOMATON. */
6499 static void
6500 set_insn_equiv_classes (automaton_t automaton)
6502 ainsn_t ainsn;
6503 ainsn_t first_insn;
6504 ainsn_t curr_insn;
6505 ainsn_t cyclic_insn_list;
6506 ainsn_t insn_with_same_reservs;
6507 int equiv_classes_num;
6509 /* All insns are included in one equivalence class. */
6510 cyclic_insn_list = NULL;
6511 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6512 if (ainsn->first_insn_with_same_reservs)
6513 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6514 cyclic_insn_list);
6515 /* Process insns in order to make equivalence partition. */
6516 pass_states (automaton, process_state_for_insn_equiv_partition);
6517 /* Enumerate equiv classes. */
6518 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6519 /* Set undefined value. */
6520 ainsn->insn_equiv_class_num = -1;
6521 equiv_classes_num = 0;
6522 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6523 if (ainsn->insn_equiv_class_num < 0)
6525 first_insn = ainsn;
6526 gcc_assert (first_insn->first_insn_with_same_reservs);
6527 first_insn->first_ainsn_with_given_equivalence_num = 1;
6528 curr_insn = first_insn;
6531 for (insn_with_same_reservs = curr_insn;
6532 insn_with_same_reservs != NULL;
6533 insn_with_same_reservs
6534 = insn_with_same_reservs->next_same_reservs_insn)
6535 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6536 curr_insn = curr_insn->next_equiv_class_insn;
6538 while (curr_insn != first_insn);
6539 equiv_classes_num++;
6541 automaton->insn_equiv_classes_num = equiv_classes_num;
6546 /* This page contains code for creating DFA(s) and calls functions
6547 building them. */
6550 /* The following value is used to prevent floating point overflow for
6551 estimating an automaton bound. The value should be less DBL_MAX on
6552 the host machine. We use here approximate minimum of maximal
6553 double floating point value required by ANSI C standard. It
6554 will work for non ANSI sun compiler too. */
6556 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6558 /* The function estimate size of the single DFA used by PHR (pipeline
6559 hazards recognizer). */
6560 static double
6561 estimate_one_automaton_bound (void)
6563 decl_t decl;
6564 double one_automaton_estimation_bound;
6565 double root_value;
6566 int i;
6568 one_automaton_estimation_bound = 1.0;
6569 for (i = 0; i < description->decls_num; i++)
6571 decl = description->decls [i];
6572 if (decl->mode == dm_unit)
6574 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6575 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6576 / automata_num);
6577 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6578 > one_automaton_estimation_bound)
6579 one_automaton_estimation_bound *= root_value;
6582 return one_automaton_estimation_bound;
6585 /* The function compares unit declarations according to their maximal
6586 cycle in reservations. */
6587 static int
6588 compare_max_occ_cycle_nums (const void *unit_decl_1,
6589 const void *unit_decl_2)
6591 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6592 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6593 return 1;
6594 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6595 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6596 return 0;
6597 else
6598 return -1;
6601 /* The function makes heuristic assigning automata to units. Actually
6602 efficacy of the algorithm has been checked yet??? */
6604 static void
6605 units_to_automata_heuristic_distr (void)
6607 double estimation_bound;
6608 int automaton_num;
6609 int rest_units_num;
6610 double bound_value;
6611 unit_decl_t *unit_decls;
6612 int i, j;
6614 if (description->units_num == 0)
6615 return;
6616 estimation_bound = estimate_one_automaton_bound ();
6617 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6619 for (i = 0, j = 0; i < description->decls_num; i++)
6620 if (description->decls[i]->mode == dm_unit)
6621 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6622 gcc_assert (j == description->units_num);
6624 qsort (unit_decls, description->units_num,
6625 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6627 automaton_num = 0;
6628 bound_value = unit_decls[0]->max_occ_cycle_num;
6629 unit_decls[0]->corresponding_automaton_num = automaton_num;
6631 for (i = 1; i < description->units_num; i++)
6633 rest_units_num = description->units_num - i + 1;
6634 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6635 if (automaton_num < automata_num - 1
6636 && ((automata_num - automaton_num - 1 == rest_units_num)
6637 || (bound_value
6638 > (estimation_bound
6639 / unit_decls[i]->max_occ_cycle_num))))
6641 bound_value = unit_decls[i]->max_occ_cycle_num;
6642 automaton_num++;
6644 else
6645 bound_value *= unit_decls[i]->max_occ_cycle_num;
6646 unit_decls[i]->corresponding_automaton_num = automaton_num;
6648 gcc_assert (automaton_num == automata_num - 1);
6649 free (unit_decls);
6652 /* The functions creates automaton insns for each automata. Automaton
6653 insn is simply insn for given automaton which makes reservation
6654 only of units of the automaton. */
6655 static void
6656 create_ainsns (automaton_t automaton)
6658 decl_t decl;
6659 ainsn_t first_ainsn;
6660 ainsn_t curr_ainsn;
6661 ainsn_t prev_ainsn;
6662 int i;
6664 first_ainsn = NULL;
6665 prev_ainsn = NULL;
6666 for (i = 0; i < description->decls_num; i++)
6668 decl = description->decls [i];
6669 if (decl->mode == dm_insn_reserv)
6671 curr_ainsn = XCREATENODE (struct ainsn);
6672 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6673 curr_ainsn->important_p = FALSE;
6674 curr_ainsn->next_ainsn = NULL;
6675 if (prev_ainsn == NULL)
6676 first_ainsn = curr_ainsn;
6677 else
6678 prev_ainsn->next_ainsn = curr_ainsn;
6679 if (decl == advance_cycle_insn_decl)
6680 automaton->advance_ainsn = curr_ainsn;
6681 else if (decl == collapse_ndfa_insn_decl)
6682 automaton->collapse_ainsn = curr_ainsn;
6683 prev_ainsn = curr_ainsn;
6686 automaton->ainsn_list = first_ainsn;
6689 /* The function assigns automata to units according to constructions
6690 `define_automaton' in the description. */
6691 static void
6692 units_to_automata_distr (void)
6694 decl_t decl;
6695 int i;
6697 for (i = 0; i < description->decls_num; i++)
6699 decl = description->decls [i];
6700 if (decl->mode == dm_unit)
6702 if (DECL_UNIT (decl)->automaton_decl == NULL
6703 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6704 == NULL))
6705 /* Distribute to the first automaton. */
6706 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6707 else
6708 DECL_UNIT (decl)->corresponding_automaton_num
6709 = (DECL_UNIT (decl)->automaton_decl
6710 ->corresponding_automaton->automaton_order_num);
6715 /* The function creates DFA(s) for fast pipeline hazards recognition
6716 after checking and simplifying IR of the description. */
6717 static void
6718 create_automata (void)
6720 automaton_t curr_automaton;
6721 automaton_t prev_automaton;
6722 decl_t decl;
6723 int curr_automaton_num;
6724 int i;
6726 if (automata_num != 0)
6728 units_to_automata_heuristic_distr ();
6729 for (prev_automaton = NULL, curr_automaton_num = 0;
6730 curr_automaton_num < automata_num;
6731 curr_automaton_num++, prev_automaton = curr_automaton)
6733 curr_automaton = XCREATENODE (struct automaton);
6734 create_ainsns (curr_automaton);
6735 curr_automaton->corresponding_automaton_decl = NULL;
6736 curr_automaton->next_automaton = NULL;
6737 curr_automaton->automaton_order_num = curr_automaton_num;
6738 if (prev_automaton == NULL)
6739 description->first_automaton = curr_automaton;
6740 else
6741 prev_automaton->next_automaton = curr_automaton;
6744 else
6746 curr_automaton_num = 0;
6747 prev_automaton = NULL;
6748 for (i = 0; i < description->decls_num; i++)
6750 decl = description->decls [i];
6751 if (decl->mode == dm_automaton
6752 && DECL_AUTOMATON (decl)->automaton_is_used)
6754 curr_automaton = XCREATENODE (struct automaton);
6755 create_ainsns (curr_automaton);
6756 curr_automaton->corresponding_automaton_decl
6757 = DECL_AUTOMATON (decl);
6758 curr_automaton->next_automaton = NULL;
6759 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6760 curr_automaton->automaton_order_num = curr_automaton_num;
6761 if (prev_automaton == NULL)
6762 description->first_automaton = curr_automaton;
6763 else
6764 prev_automaton->next_automaton = curr_automaton;
6765 curr_automaton_num++;
6766 prev_automaton = curr_automaton;
6769 if (curr_automaton_num == 0)
6771 curr_automaton = XCREATENODE (struct automaton);
6772 create_ainsns (curr_automaton);
6773 curr_automaton->corresponding_automaton_decl = NULL;
6774 curr_automaton->next_automaton = NULL;
6775 description->first_automaton = curr_automaton;
6777 units_to_automata_distr ();
6779 NDFA_time = create_ticker ();
6780 ticker_off (&NDFA_time);
6781 NDFA_to_DFA_time = create_ticker ();
6782 ticker_off (&NDFA_to_DFA_time);
6783 minimize_time = create_ticker ();
6784 ticker_off (&minimize_time);
6785 equiv_time = create_ticker ();
6786 ticker_off (&equiv_time);
6787 for (curr_automaton = description->first_automaton;
6788 curr_automaton != NULL;
6789 curr_automaton = curr_automaton->next_automaton)
6791 if (progress_flag)
6793 if (curr_automaton->corresponding_automaton_decl == NULL)
6794 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6795 else
6796 fprintf (stderr, "Prepare automaton `%s' creation...",
6797 curr_automaton->corresponding_automaton_decl->name);
6799 create_alt_states (curr_automaton);
6800 form_ainsn_with_same_reservs (curr_automaton);
6801 if (progress_flag)
6802 fprintf (stderr, "done\n");
6803 build_automaton (curr_automaton);
6804 enumerate_states (curr_automaton);
6805 ticker_on (&equiv_time);
6806 set_insn_equiv_classes (curr_automaton);
6807 ticker_off (&equiv_time);
6813 /* This page contains code for forming string representation of
6814 regexp. The representation is formed on IR obstack. So you should
6815 not work with IR obstack between regexp_representation and
6816 finish_regexp_representation calls. */
6818 /* This recursive function forms string representation of regexp
6819 (without tailing '\0'). */
6820 static void
6821 form_regexp (regexp_t regexp)
6823 int i;
6825 switch (regexp->mode)
6827 case rm_unit: case rm_reserv:
6829 const char *name = (regexp->mode == rm_unit
6830 ? REGEXP_UNIT (regexp)->name
6831 : REGEXP_RESERV (regexp)->name);
6833 obstack_grow (&irp, name, strlen (name));
6834 break;
6837 case rm_sequence:
6838 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6840 if (i != 0)
6841 obstack_1grow (&irp, ',');
6842 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6844 break;
6846 case rm_allof:
6847 obstack_1grow (&irp, '(');
6848 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6850 if (i != 0)
6851 obstack_1grow (&irp, '+');
6852 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6853 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6854 obstack_1grow (&irp, '(');
6855 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6856 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6857 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6858 obstack_1grow (&irp, ')');
6860 obstack_1grow (&irp, ')');
6861 break;
6863 case rm_oneof:
6864 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6866 if (i != 0)
6867 obstack_1grow (&irp, '|');
6868 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6869 obstack_1grow (&irp, '(');
6870 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6871 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6872 obstack_1grow (&irp, ')');
6874 break;
6876 case rm_repeat:
6878 char digits [30];
6880 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6881 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6882 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6883 obstack_1grow (&irp, '(');
6884 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6885 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6886 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6887 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6888 obstack_1grow (&irp, ')');
6889 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6890 obstack_grow (&irp, digits, strlen (digits));
6891 break;
6894 case rm_nothing:
6895 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6896 break;
6898 default:
6899 gcc_unreachable ();
6903 /* The function returns string representation of REGEXP on IR
6904 obstack. */
6905 static const char *
6906 regexp_representation (regexp_t regexp)
6908 form_regexp (regexp);
6909 obstack_1grow (&irp, '\0');
6910 return obstack_base (&irp);
6913 /* The function frees memory allocated for last formed string
6914 representation of regexp. */
6915 static void
6916 finish_regexp_representation (void)
6918 int length = obstack_object_size (&irp);
6920 obstack_blank_fast (&irp, -length);
6925 /* This page contains code for output PHR (pipeline hazards recognizer). */
6927 /* The function outputs minimal C type which is sufficient for
6928 representation numbers in range min_range_value and
6929 max_range_value. Because host machine and build machine may be
6930 different, we use here minimal values required by ANSI C standard
6931 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6932 approximation. */
6934 static void
6935 output_range_type (FILE *f, long int min_range_value,
6936 long int max_range_value)
6938 if (min_range_value >= 0 && max_range_value <= 255)
6939 fprintf (f, "unsigned char");
6940 else if (min_range_value >= -127 && max_range_value <= 127)
6941 fprintf (f, "signed char");
6942 else if (min_range_value >= 0 && max_range_value <= 65535)
6943 fprintf (f, "unsigned short");
6944 else if (min_range_value >= -32767 && max_range_value <= 32767)
6945 fprintf (f, "short");
6946 else
6947 fprintf (f, "int");
6950 /* The function outputs all initialization values of VECT. */
6951 static void
6952 output_vect (vla_hwint_t vect)
6954 int els_on_line;
6955 size_t vect_length = VEC_length (vect_el_t, vect);
6956 size_t i;
6958 els_on_line = 1;
6959 if (vect_length == 0)
6960 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6961 else
6962 for (i = 0; i < vect_length; i++)
6964 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6965 if (els_on_line == 10)
6967 els_on_line = 0;
6968 fputs (",\n", output_file);
6970 else if (i < vect_length-1)
6971 fputs (", ", output_file);
6972 els_on_line++;
6976 /* The following is name of the structure which represents DFA(s) for
6977 PHR. */
6978 #define CHIP_NAME "DFA_chip"
6980 /* The following is name of member which represents state of a DFA for
6981 PHR. */
6982 static void
6983 output_chip_member_name (FILE *f, automaton_t automaton)
6985 if (automaton->corresponding_automaton_decl == NULL)
6986 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6987 else
6988 fprintf (f, "%s_automaton_state",
6989 automaton->corresponding_automaton_decl->name);
6992 /* The following is name of temporary variable which stores state of a
6993 DFA for PHR. */
6994 static void
6995 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6997 fprintf (f, "_");
6998 output_chip_member_name (f, automaton);
7001 /* This is name of macro value which is code of pseudo_insns
7002 representing advancing cpu cycle and collapsing the NDFA.
7003 Its value is used as internal code unknown insn. */
7004 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7005 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
7007 /* Output name of translate vector for given automaton. */
7008 static void
7009 output_translate_vect_name (FILE *f, automaton_t automaton)
7011 if (automaton->corresponding_automaton_decl == NULL)
7012 fprintf (f, "translate_%d", automaton->automaton_order_num);
7013 else
7014 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
7017 /* Output name for simple transition table representation. */
7018 static void
7019 output_trans_full_vect_name (FILE *f, automaton_t automaton)
7021 if (automaton->corresponding_automaton_decl == NULL)
7022 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7023 else
7024 fprintf (f, "%s_transitions",
7025 automaton->corresponding_automaton_decl->name);
7028 /* Output name of comb vector of the transition table for given
7029 automaton. */
7030 static void
7031 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7033 if (automaton->corresponding_automaton_decl == NULL)
7034 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7035 else
7036 fprintf (f, "%s_transitions",
7037 automaton->corresponding_automaton_decl->name);
7040 /* Output name of check vector of the transition table for given
7041 automaton. */
7042 static void
7043 output_trans_check_vect_name (FILE *f, automaton_t automaton)
7045 if (automaton->corresponding_automaton_decl == NULL)
7046 fprintf (f, "check_%d", automaton->automaton_order_num);
7047 else
7048 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7051 /* Output name of base vector of the transition table for given
7052 automaton. */
7053 static void
7054 output_trans_base_vect_name (FILE *f, automaton_t automaton)
7056 if (automaton->corresponding_automaton_decl == NULL)
7057 fprintf (f, "base_%d", automaton->automaton_order_num);
7058 else
7059 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7062 /* Output name of simple min issue delay table representation. */
7063 static void
7064 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7066 if (automaton->corresponding_automaton_decl == NULL)
7067 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7068 else
7069 fprintf (f, "%s_min_issue_delay",
7070 automaton->corresponding_automaton_decl->name);
7073 /* Output name of deadlock vector for given automaton. */
7074 static void
7075 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7077 if (automaton->corresponding_automaton_decl == NULL)
7078 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7079 else
7080 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7083 /* Output name of reserved units table for AUTOMATON into file F. */
7084 static void
7085 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7087 if (automaton->corresponding_automaton_decl == NULL)
7088 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7089 else
7090 fprintf (f, "%s_reserved_units",
7091 automaton->corresponding_automaton_decl->name);
7094 /* Name of the PHR interface macro. */
7095 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7097 /* Names of an internal functions: */
7098 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7100 /* This is external type of DFA(s) state. */
7101 #define STATE_TYPE_NAME "state_t"
7103 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7105 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7107 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7109 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7111 /* Name of cache of insn dfa codes. */
7112 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7114 /* Name of length of cache of insn dfa codes. */
7115 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7117 /* Names of the PHR interface functions: */
7118 #define SIZE_FUNC_NAME "state_size"
7120 #define TRANSITION_FUNC_NAME "state_transition"
7122 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7124 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7126 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7128 #define RESET_FUNC_NAME "state_reset"
7130 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7132 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7134 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7136 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7138 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7140 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7142 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7144 #define DFA_START_FUNC_NAME "dfa_start"
7146 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7148 /* Names of parameters of the PHR interface functions. */
7149 #define STATE_NAME "state"
7151 #define INSN_PARAMETER_NAME "insn"
7153 #define INSN2_PARAMETER_NAME "insn2"
7155 #define CHIP_PARAMETER_NAME "chip"
7157 #define FILE_PARAMETER_NAME "f"
7159 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7161 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7163 /* Names of the variables whose values are internal insn code of rtx
7164 insn. */
7165 #define INTERNAL_INSN_CODE_NAME "insn_code"
7167 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7169 /* Names of temporary variables in some functions. */
7170 #define TEMPORARY_VARIABLE_NAME "temp"
7172 #define I_VARIABLE_NAME "i"
7174 /* Name of result variable in some functions. */
7175 #define RESULT_VARIABLE_NAME "res"
7177 /* Name of function (attribute) to translate insn into internal insn
7178 code. */
7179 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7181 /* Name of function (attribute) to translate insn into internal insn
7182 code with caching. */
7183 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7185 /* Output C type which is used for representation of codes of states
7186 of AUTOMATON. */
7187 static void
7188 output_state_member_type (FILE *f, automaton_t automaton)
7190 output_range_type (f, 0, automaton->achieved_states_num);
7193 /* Output definition of the structure representing current DFA(s)
7194 state(s). */
7195 static void
7196 output_chip_definitions (void)
7198 automaton_t automaton;
7200 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7201 for (automaton = description->first_automaton;
7202 automaton != NULL;
7203 automaton = automaton->next_automaton)
7205 fprintf (output_file, " ");
7206 output_state_member_type (output_file, automaton);
7207 fprintf (output_file, " ");
7208 output_chip_member_name (output_file, automaton);
7209 fprintf (output_file, ";\n");
7211 fprintf (output_file, "};\n\n");
7212 #if 0
7213 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7214 #endif
7218 /* The function outputs translate vector of internal insn code into
7219 insn equivalence class number. The equivalence class number is
7220 used to access to table and vectors representing DFA(s). */
7221 static void
7222 output_translate_vect (automaton_t automaton)
7224 ainsn_t ainsn;
7225 int insn_value;
7226 vla_hwint_t translate_vect;
7228 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7230 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7231 /* Undefined value */
7232 VEC_quick_push (vect_el_t, translate_vect,
7233 automaton->insn_equiv_classes_num);
7235 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7236 VEC_replace (vect_el_t, translate_vect,
7237 ainsn->insn_reserv_decl->insn_num,
7238 ainsn->insn_equiv_class_num);
7240 fprintf (output_file,
7241 "/* Vector translating external insn codes to internal ones.*/\n");
7242 fprintf (output_file, "static const ");
7243 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7244 fprintf (output_file, " ");
7245 output_translate_vect_name (output_file, automaton);
7246 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7247 output_vect (translate_vect);
7248 fprintf (output_file, "};\n\n");
7249 VEC_free (vect_el_t, heap, translate_vect);
7252 /* The value in a table state x ainsn -> something which represents
7253 undefined value. */
7254 static int undefined_vect_el_value;
7256 /* The following function returns nonzero value if the best
7257 representation of the table is comb vector. */
7258 static int
7259 comb_vect_p (state_ainsn_table_t tab)
7261 if (no_comb_flag)
7262 return false;
7263 return (2 * VEC_length (vect_el_t, tab->full_vect)
7264 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7267 /* The following function creates new table for AUTOMATON. */
7268 static state_ainsn_table_t
7269 create_state_ainsn_table (automaton_t automaton)
7271 state_ainsn_table_t tab;
7272 int full_vect_length;
7273 int i;
7275 tab = XCREATENODE (struct state_ainsn_table);
7276 tab->automaton = automaton;
7278 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7279 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7281 tab->base_vect = 0;
7282 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7283 automaton->achieved_states_num);
7285 full_vect_length = (automaton->insn_equiv_classes_num
7286 * automaton->achieved_states_num);
7287 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7288 for (i = 0; i < full_vect_length; i++)
7289 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7291 tab->min_base_vect_el_value = 0;
7292 tab->max_base_vect_el_value = 0;
7293 tab->min_comb_vect_el_value = 0;
7294 tab->max_comb_vect_el_value = 0;
7295 return tab;
7298 /* The following function outputs the best C representation of the
7299 table TAB of given TABLE_NAME. */
7300 static void
7301 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7302 void (*output_full_vect_name_func) (FILE *, automaton_t),
7303 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7304 void (*output_check_vect_name_func) (FILE *, automaton_t),
7305 void (*output_base_vect_name_func) (FILE *, automaton_t))
7307 if (!comb_vect_p (tab))
7309 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7310 fprintf (output_file, "static const ");
7311 output_range_type (output_file, tab->min_comb_vect_el_value,
7312 tab->max_comb_vect_el_value);
7313 fprintf (output_file, " ");
7314 (*output_full_vect_name_func) (output_file, tab->automaton);
7315 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7316 output_vect (tab->full_vect);
7317 fprintf (output_file, "};\n\n");
7319 else
7321 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7322 fprintf (output_file, "static const ");
7323 output_range_type (output_file, tab->min_comb_vect_el_value,
7324 tab->max_comb_vect_el_value);
7325 fprintf (output_file, " ");
7326 (*output_comb_vect_name_func) (output_file, tab->automaton);
7327 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7328 output_vect (tab->comb_vect);
7329 fprintf (output_file, "};\n\n");
7330 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7331 fprintf (output_file, "static const ");
7332 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7333 fprintf (output_file, " ");
7334 (*output_check_vect_name_func) (output_file, tab->automaton);
7335 fprintf (output_file, "[] = {\n");
7336 output_vect (tab->check_vect);
7337 fprintf (output_file, "};\n\n");
7338 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7339 fprintf (output_file, "static const ");
7340 output_range_type (output_file, tab->min_base_vect_el_value,
7341 tab->max_base_vect_el_value);
7342 fprintf (output_file, " ");
7343 (*output_base_vect_name_func) (output_file, tab->automaton);
7344 fprintf (output_file, "[] = {\n");
7345 output_vect (tab->base_vect);
7346 fprintf (output_file, "};\n\n");
7350 /* The following function adds vector VECT to table TAB as its line
7351 with number VECT_NUM. */
7352 static void
7353 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7355 int vect_length;
7356 size_t real_vect_length;
7357 int comb_vect_index;
7358 int comb_vect_els_num;
7359 int vect_index;
7360 int first_unempty_vect_index;
7361 int additional_els_num;
7362 int no_state_value;
7363 vect_el_t vect_el;
7364 int i;
7365 unsigned long vect_mask, comb_vect_mask;
7367 vect_length = VEC_length (vect_el_t, vect);
7368 gcc_assert (vect_length);
7369 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7370 real_vect_length = tab->automaton->insn_equiv_classes_num;
7371 /* Form full vector in the table: */
7373 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7374 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7375 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7376 full_base + vect_length);
7377 for (i = 0; i < vect_length; i++)
7378 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7379 VEC_index (vect_el_t, vect, i));
7382 /* The comb_vect min/max values are also used for the full vector, so
7383 compute them now. */
7384 for (vect_index = 0; vect_index < vect_length; vect_index++)
7385 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7387 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7388 gcc_assert (x >= 0);
7389 if (tab->max_comb_vect_el_value < x)
7390 tab->max_comb_vect_el_value = x;
7391 if (tab->min_comb_vect_el_value > x)
7392 tab->min_comb_vect_el_value = x;
7394 if (no_comb_flag)
7395 return;
7397 /* Form comb vector in the table: */
7398 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7399 == VEC_length (vect_el_t, tab->check_vect));
7401 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7402 for (first_unempty_vect_index = 0;
7403 first_unempty_vect_index < vect_length;
7404 first_unempty_vect_index++)
7405 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7406 != undefined_vect_el_value)
7407 break;
7409 /* Search for the place in comb vect for the inserted vect. */
7411 /* Slow case. */
7412 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7414 for (comb_vect_index = 0;
7415 comb_vect_index < comb_vect_els_num;
7416 comb_vect_index++)
7418 for (vect_index = first_unempty_vect_index;
7419 vect_index < vect_length
7420 && vect_index + comb_vect_index < comb_vect_els_num;
7421 vect_index++)
7422 if (VEC_index (vect_el_t, vect, vect_index)
7423 != undefined_vect_el_value
7424 && (VEC_index (vect_el_t, tab->comb_vect,
7425 vect_index + comb_vect_index)
7426 != undefined_vect_el_value))
7427 break;
7428 if (vect_index >= vect_length
7429 || vect_index + comb_vect_index >= comb_vect_els_num)
7430 break;
7432 goto found;
7435 /* Fast case. */
7436 vect_mask = 0;
7437 for (vect_index = first_unempty_vect_index;
7438 vect_index < vect_length;
7439 vect_index++)
7441 vect_mask = vect_mask << 1;
7442 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7443 vect_mask |= 1;
7446 /* Search for the place in comb vect for the inserted vect. */
7447 comb_vect_index = 0;
7448 if (comb_vect_els_num == 0)
7449 goto found;
7451 comb_vect_mask = 0;
7452 for (vect_index = first_unempty_vect_index;
7453 vect_index < vect_length && vect_index < comb_vect_els_num;
7454 vect_index++)
7456 comb_vect_mask <<= 1;
7457 if (vect_index + comb_vect_index < comb_vect_els_num
7458 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7459 != undefined_vect_el_value)
7460 comb_vect_mask |= 1;
7462 if ((vect_mask & comb_vect_mask) == 0)
7463 goto found;
7465 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7466 comb_vect_index++, i++)
7468 comb_vect_mask = (comb_vect_mask << 1) | 1;
7469 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7470 == undefined_vect_el_value);
7471 if ((vect_mask & comb_vect_mask) == 0)
7472 goto found;
7474 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7476 comb_vect_mask <<= 1;
7477 if ((vect_mask & comb_vect_mask) == 0)
7478 goto found;
7481 found:
7482 /* Slot was found. */
7483 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7484 if (additional_els_num < 0)
7485 additional_els_num = 0;
7486 /* Expand comb and check vectors. */
7487 vect_el = undefined_vect_el_value;
7488 no_state_value = tab->automaton->achieved_states_num;
7489 while (additional_els_num > 0)
7491 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7492 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7493 additional_els_num--;
7495 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7496 >= comb_vect_index + real_vect_length);
7497 /* Fill comb and check vectors. */
7498 for (vect_index = 0; vect_index < vect_length; vect_index++)
7499 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7501 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7502 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7503 comb_vect_index + vect_index)
7504 == undefined_vect_el_value);
7505 gcc_assert (x >= 0);
7506 VEC_replace (vect_el_t, tab->comb_vect,
7507 comb_vect_index + vect_index, x);
7508 VEC_replace (vect_el_t, tab->check_vect,
7509 comb_vect_index + vect_index, vect_num);
7511 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7512 tab->max_comb_vect_el_value = undefined_vect_el_value;
7513 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7514 tab->min_comb_vect_el_value = undefined_vect_el_value;
7515 if (tab->max_base_vect_el_value < comb_vect_index)
7516 tab->max_base_vect_el_value = comb_vect_index;
7517 if (tab->min_base_vect_el_value > comb_vect_index)
7518 tab->min_base_vect_el_value = comb_vect_index;
7520 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7523 /* Return number of out arcs of STATE. */
7524 static int
7525 out_state_arcs_num (const_state_t state)
7527 int result;
7528 arc_t arc;
7530 result = 0;
7531 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7533 gcc_assert (arc->insn);
7534 if (arc->insn->first_ainsn_with_given_equivalence_num)
7535 result++;
7537 return result;
7540 /* Compare number of possible transitions from the states. */
7541 static int
7542 compare_transition_els_num (const void *state_ptr_1,
7543 const void *state_ptr_2)
7545 const int transition_els_num_1
7546 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7547 const int transition_els_num_2
7548 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7550 if (transition_els_num_1 < transition_els_num_2)
7551 return 1;
7552 else if (transition_els_num_1 == transition_els_num_2)
7553 return 0;
7554 else
7555 return -1;
7558 /* The function adds element EL_VALUE to vector VECT for a table state
7559 x AINSN. */
7560 static void
7561 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7563 int equiv_class_num;
7564 int vect_index;
7566 gcc_assert (ainsn);
7567 equiv_class_num = ainsn->insn_equiv_class_num;
7568 for (vect_index = VEC_length (vect_el_t, *vect);
7569 vect_index <= equiv_class_num;
7570 vect_index++)
7571 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7572 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7575 /* This is for forming vector of states of an automaton. */
7576 static VEC(state_t, heap) *output_states_vect;
7578 /* The function is called by function pass_states. The function adds
7579 STATE to `output_states_vect'. */
7580 static void
7581 add_states_vect_el (state_t state)
7583 VEC_safe_push (state_t, heap, output_states_vect, state);
7586 /* Form and output vectors (comb, check, base or full vector)
7587 representing transition table of AUTOMATON. */
7588 static void
7589 output_trans_table (automaton_t automaton)
7591 size_t i;
7592 arc_t arc;
7593 vla_hwint_t transition_vect = 0;
7595 undefined_vect_el_value = automaton->achieved_states_num;
7596 automaton->trans_table = create_state_ainsn_table (automaton);
7597 /* Create vect of pointers to states ordered by num of transitions
7598 from the state (state with the maximum num is the first). */
7599 output_states_vect = 0;
7600 pass_states (automaton, add_states_vect_el);
7601 VEC_qsort (state_t, output_states_vect, compare_transition_els_num);
7603 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7605 VEC_truncate (vect_el_t, transition_vect, 0);
7606 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7607 arc != NULL;
7608 arc = next_out_arc (arc))
7610 gcc_assert (arc->insn);
7611 if (arc->insn->first_ainsn_with_given_equivalence_num)
7612 add_vect_el (&transition_vect, arc->insn,
7613 arc->to_state->order_state_num);
7615 add_vect (automaton->trans_table,
7616 VEC_index (state_t, output_states_vect, i)->order_state_num,
7617 transition_vect);
7619 output_state_ainsn_table
7620 (automaton->trans_table, "state transitions",
7621 output_trans_full_vect_name, output_trans_comb_vect_name,
7622 output_trans_check_vect_name, output_trans_base_vect_name);
7624 VEC_free (state_t, heap, output_states_vect);
7625 VEC_free (vect_el_t, heap, transition_vect);
7628 /* Form and output vectors representing minimal issue delay table of
7629 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7630 the ainsn. */
7631 static void
7632 output_min_issue_delay_table (automaton_t automaton)
7634 vla_hwint_t min_issue_delay_vect;
7635 vla_hwint_t compressed_min_issue_delay_vect;
7636 ainsn_t ainsn;
7637 size_t i;
7638 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7639 size_t cfactor;
7640 int changed;
7642 /* Create vect of pointers to states ordered by num of transitions
7643 from the state (state with the maximum num is the first). */
7644 output_states_vect = 0;
7645 pass_states (automaton, add_states_vect_el);
7647 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7648 * automaton->insn_equiv_classes_num);
7649 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7650 for (i = 0; i < min_issue_delay_len; i++)
7651 VEC_quick_push (vect_el_t, min_issue_delay_vect, -1);
7653 automaton->max_min_delay = 0;
7657 size_t state_no;
7659 changed = 0;
7661 for (state_no = 0; state_no < VEC_length (state_t, output_states_vect);
7662 state_no++)
7664 state_t s = VEC_index (state_t, output_states_vect, state_no);
7665 arc_t arc;
7667 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7669 int k;
7671 size_t asn = s->order_state_num
7672 * automaton->insn_equiv_classes_num
7673 + arc->insn->insn_equiv_class_num;
7675 if (VEC_index (vect_el_t, min_issue_delay_vect, asn))
7677 VEC_replace (vect_el_t, min_issue_delay_vect, asn,
7678 (vect_el_t) 0);
7679 changed = 1;
7682 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7684 size_t n0, n1;
7685 vect_el_t delay0, delay1;
7687 n0 = s->order_state_num
7688 * automaton->insn_equiv_classes_num
7689 + k;
7690 n1 = arc->to_state->order_state_num
7691 * automaton->insn_equiv_classes_num
7692 + k;
7693 delay0 = VEC_index (vect_el_t, min_issue_delay_vect, n0);
7694 delay1 = VEC_index (vect_el_t, min_issue_delay_vect, n1);
7695 if (delay1 != -1)
7697 if (arc->insn->insn_reserv_decl
7698 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7699 delay1++;
7700 if (delay1 < delay0 || delay0 == -1)
7702 VEC_replace (vect_el_t, min_issue_delay_vect, n0, delay1);
7703 changed = 1;
7710 while (changed);
7712 automaton->max_min_delay = 0;
7714 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7715 if (ainsn->first_ainsn_with_given_equivalence_num)
7717 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7719 state_t s = VEC_index (state_t, output_states_vect, i);
7720 size_t np = s->order_state_num
7721 * automaton->insn_equiv_classes_num
7722 + ainsn->insn_equiv_class_num;
7723 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, np);
7725 if (automaton->max_min_delay < x)
7726 automaton->max_min_delay = x;
7727 if (x == -1)
7728 VEC_replace (vect_el_t, min_issue_delay_vect, np,
7729 (vect_el_t) 0);
7733 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7734 fprintf (output_file, "static const ");
7735 output_range_type (output_file, 0, automaton->max_min_delay);
7736 fprintf (output_file, " ");
7737 output_min_issue_delay_vect_name (output_file, automaton);
7738 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7739 /* Compress the vector. */
7740 if (automaton->max_min_delay < 2)
7741 cfactor = 8;
7742 else if (automaton->max_min_delay < 4)
7743 cfactor = 4;
7744 else if (automaton->max_min_delay < 16)
7745 cfactor = 2;
7746 else
7747 cfactor = 1;
7748 automaton->min_issue_delay_table_compression_factor = cfactor;
7750 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7751 compressed_min_issue_delay_vect
7752 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7754 for (i = 0; i < compressed_min_issue_delay_len; i++)
7755 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7757 for (i = 0; i < min_issue_delay_len; i++)
7759 size_t ci = i / cfactor;
7760 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7761 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7763 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7764 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7766 output_vect (compressed_min_issue_delay_vect);
7767 fprintf (output_file, "};\n\n");
7768 VEC_free (state_t, heap, output_states_vect);
7769 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7770 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7773 /* Form and output vector representing the locked states of
7774 AUTOMATON. */
7775 static void
7776 output_dead_lock_vect (automaton_t automaton)
7778 size_t i;
7779 arc_t arc;
7780 vla_hwint_t dead_lock_vect = 0;
7782 /* Create vect of pointers to states ordered by num of
7783 transitions from the state (state with the maximum num is the
7784 first). */
7785 automaton->locked_states = 0;
7786 output_states_vect = 0;
7787 pass_states (automaton, add_states_vect_el);
7789 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7790 VEC_length (state_t, output_states_vect));
7791 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7793 state_t s = VEC_index (state_t, output_states_vect, i);
7794 arc = first_out_arc (s);
7795 gcc_assert (arc);
7796 if (next_out_arc (arc) == NULL
7797 && (arc->insn->insn_reserv_decl
7798 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7800 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7801 automaton->locked_states++;
7803 else
7804 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num,
7805 (vect_el_t) 0);
7807 if (automaton->locked_states == 0)
7808 return;
7810 fprintf (output_file, "/* Vector for locked state flags. */\n");
7811 fprintf (output_file, "static const ");
7812 output_range_type (output_file, 0, 1);
7813 fprintf (output_file, " ");
7814 output_dead_lock_vect_name (output_file, automaton);
7815 fprintf (output_file, "[] = {\n");
7816 output_vect (dead_lock_vect);
7817 fprintf (output_file, "};\n\n");
7818 VEC_free (state_t, heap, output_states_vect);
7819 VEC_free (vect_el_t, heap, dead_lock_vect);
7822 /* Form and output vector representing reserved units of the states of
7823 AUTOMATON. */
7824 static void
7825 output_reserved_units_table (automaton_t automaton)
7827 vla_hwint_t reserved_units_table = 0;
7828 int state_byte_size;
7829 int reserved_units_size;
7830 size_t n;
7831 int i;
7833 if (description->query_units_num == 0)
7834 return;
7836 /* Create vect of pointers to states. */
7837 output_states_vect = 0;
7838 pass_states (automaton, add_states_vect_el);
7839 /* Create vector. */
7840 state_byte_size = (description->query_units_num + 7) / 8;
7841 reserved_units_size = (VEC_length (state_t, output_states_vect)
7842 * state_byte_size);
7844 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7846 for (i = 0; i < reserved_units_size; i++)
7847 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7848 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7850 state_t s = VEC_index (state_t, output_states_vect, n);
7851 for (i = 0; i < description->units_num; i++)
7852 if (units_array [i]->query_p
7853 && first_cycle_unit_presence (s, i))
7855 int ri = (s->order_state_num * state_byte_size
7856 + units_array [i]->query_num / 8);
7857 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7859 x += 1 << (units_array [i]->query_num % 8);
7860 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7863 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7864 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7865 fprintf (output_file, "static const ");
7866 output_range_type (output_file, 0, 255);
7867 fprintf (output_file, " ");
7868 output_reserved_units_table_name (output_file, automaton);
7869 fprintf (output_file, "[] = {\n");
7870 output_vect (reserved_units_table);
7871 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7872 CPU_UNITS_QUERY_MACRO_NAME);
7874 VEC_free (state_t, heap, output_states_vect);
7875 VEC_free (vect_el_t, heap, reserved_units_table);
7878 /* The function outputs all tables representing DFA(s) used for fast
7879 pipeline hazards recognition. */
7880 static void
7881 output_tables (void)
7883 automaton_t automaton;
7885 for (automaton = description->first_automaton;
7886 automaton != NULL;
7887 automaton = automaton->next_automaton)
7889 output_translate_vect (automaton);
7890 output_trans_table (automaton);
7891 output_min_issue_delay_table (automaton);
7892 output_dead_lock_vect (automaton);
7893 output_reserved_units_table (automaton);
7895 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7896 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7897 if (collapse_flag)
7898 fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
7899 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
7902 /* The function outputs definition and value of PHR interface variable
7903 `max_insn_queue_index'. Its value is not less than maximal queue
7904 length needed for the insn scheduler. */
7905 static void
7906 output_max_insn_queue_index_def (void)
7908 int i, max, latency;
7909 decl_t decl;
7911 max = description->max_insn_reserv_cycles;
7912 for (i = 0; i < description->decls_num; i++)
7914 decl = description->decls [i];
7915 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7917 latency = DECL_INSN_RESERV (decl)->default_latency;
7918 if (latency > max)
7919 max = latency;
7921 else if (decl->mode == dm_bypass)
7923 latency = DECL_BYPASS (decl)->latency;
7924 if (latency > max)
7925 max = latency;
7928 for (i = 0; (1 << i) <= max; i++)
7930 gcc_assert (i >= 0);
7931 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7932 (1 << i) - 1);
7935 /* The function outputs switch cases for insn reservations using
7936 function *output_automata_list_code. */
7937 static void
7938 output_insn_code_cases (void (*output_automata_list_code)
7939 (automata_list_el_t))
7941 decl_t decl, decl2;
7942 int i, j;
7944 for (i = 0; i < description->decls_num; i++)
7946 decl = description->decls [i];
7947 if (decl->mode == dm_insn_reserv)
7948 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7950 for (i = 0; i < description->decls_num; i++)
7952 decl = description->decls [i];
7953 if (decl->mode == dm_insn_reserv
7954 && !DECL_INSN_RESERV (decl)->processed_p)
7956 for (j = i; j < description->decls_num; j++)
7958 decl2 = description->decls [j];
7959 if (decl2->mode == dm_insn_reserv
7960 && (DECL_INSN_RESERV (decl2)->important_automata_list
7961 == DECL_INSN_RESERV (decl)->important_automata_list))
7963 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7964 fprintf (output_file, " case %d: /* %s */\n",
7965 DECL_INSN_RESERV (decl2)->insn_num,
7966 DECL_INSN_RESERV (decl2)->name);
7969 (*output_automata_list_code)
7970 (DECL_INSN_RESERV (decl)->important_automata_list);
7976 /* The function outputs a code for evaluation of a minimal delay of
7977 issue of insns which have reservations in given AUTOMATA_LIST. */
7978 static void
7979 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7981 automata_list_el_t el;
7982 automaton_t automaton;
7984 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7986 automaton = el->automaton;
7987 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7988 output_min_issue_delay_vect_name (output_file, automaton);
7989 fprintf (output_file,
7990 (automaton->min_issue_delay_table_compression_factor != 1
7991 ? " [(" : " ["));
7992 output_translate_vect_name (output_file, automaton);
7993 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7994 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7995 output_chip_member_name (output_file, automaton);
7996 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7997 if (automaton->min_issue_delay_table_compression_factor == 1)
7998 fprintf (output_file, "];\n");
7999 else
8001 fprintf (output_file, ") / %d];\n",
8002 automaton->min_issue_delay_table_compression_factor);
8003 fprintf (output_file, " %s = (%s >> (8 - ((",
8004 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8005 output_translate_vect_name (output_file, automaton);
8006 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8007 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8008 output_chip_member_name (output_file, automaton);
8009 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
8010 fprintf
8011 (output_file, " %% %d + 1) * %d)) & %d;\n",
8012 automaton->min_issue_delay_table_compression_factor,
8013 8 / automaton->min_issue_delay_table_compression_factor,
8014 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8015 - 1);
8017 if (el == automata_list)
8018 fprintf (output_file, " %s = %s;\n",
8019 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8020 else
8022 fprintf (output_file, " if (%s > %s)\n",
8023 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8024 fprintf (output_file, " %s = %s;\n",
8025 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8028 fprintf (output_file, " break;\n\n");
8031 /* Output function `internal_min_issue_delay'. */
8032 static void
8033 output_internal_min_issue_delay_func (void)
8035 fprintf (output_file,
8036 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8037 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8038 CHIP_NAME, CHIP_PARAMETER_NAME);
8039 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8040 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8041 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8042 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8043 fprintf (output_file,
8044 "\n default:\n %s = -1;\n break;\n }\n",
8045 RESULT_VARIABLE_NAME);
8046 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8047 fprintf (output_file, "}\n\n");
8050 /* The function outputs a code changing state after issue of insns
8051 which have reservations in given AUTOMATA_LIST. */
8052 static void
8053 output_automata_list_transition_code (automata_list_el_t automata_list)
8055 automata_list_el_t el, next_el;
8057 fprintf (output_file, " {\n");
8058 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8059 for (el = automata_list;; el = next_el)
8061 next_el = el->next_automata_list_el;
8062 if (next_el == NULL)
8063 break;
8064 fprintf (output_file, " ");
8065 output_state_member_type (output_file, el->automaton);
8066 fprintf (output_file, " ");
8067 output_temp_chip_member_name (output_file, el->automaton);
8068 fprintf (output_file, ";\n");
8070 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8071 if (comb_vect_p (el->automaton->trans_table))
8073 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8074 output_trans_base_vect_name (output_file, el->automaton);
8075 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8076 output_chip_member_name (output_file, el->automaton);
8077 fprintf (output_file, "] + ");
8078 output_translate_vect_name (output_file, el->automaton);
8079 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8080 fprintf (output_file, " if (");
8081 output_trans_check_vect_name (output_file, el->automaton);
8082 fprintf (output_file, " [%s] != %s->",
8083 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8084 output_chip_member_name (output_file, el->automaton);
8085 fprintf (output_file, ")\n");
8086 fprintf (output_file, " return %s (%s, %s);\n",
8087 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8088 CHIP_PARAMETER_NAME);
8089 fprintf (output_file, " else\n");
8090 fprintf (output_file, " ");
8091 if (el->next_automata_list_el != NULL)
8092 output_temp_chip_member_name (output_file, el->automaton);
8093 else
8095 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8096 output_chip_member_name (output_file, el->automaton);
8098 fprintf (output_file, " = ");
8099 output_trans_comb_vect_name (output_file, el->automaton);
8100 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8102 else
8104 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8105 output_trans_full_vect_name (output_file, el->automaton);
8106 fprintf (output_file, " [");
8107 output_translate_vect_name (output_file, el->automaton);
8108 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8109 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8110 output_chip_member_name (output_file, el->automaton);
8111 fprintf (output_file, " * %d];\n",
8112 el->automaton->insn_equiv_classes_num);
8113 fprintf (output_file, " if (%s >= %d)\n",
8114 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8115 fprintf (output_file, " return %s (%s, %s);\n",
8116 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8117 CHIP_PARAMETER_NAME);
8118 fprintf (output_file, " else\n ");
8119 if (el->next_automata_list_el != NULL)
8120 output_temp_chip_member_name (output_file, el->automaton);
8121 else
8123 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8124 output_chip_member_name (output_file, el->automaton);
8126 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8128 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8129 for (el = automata_list;; el = next_el)
8131 next_el = el->next_automata_list_el;
8132 if (next_el == NULL)
8133 break;
8134 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8135 output_chip_member_name (output_file, el->automaton);
8136 fprintf (output_file, " = ");
8137 output_temp_chip_member_name (output_file, el->automaton);
8138 fprintf (output_file, ";\n");
8140 fprintf (output_file, " return -1;\n");
8141 fprintf (output_file, " }\n");
8144 /* Output function `internal_state_transition'. */
8145 static void
8146 output_internal_trans_func (void)
8148 fprintf (output_file,
8149 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8150 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8151 CHIP_NAME, CHIP_PARAMETER_NAME);
8152 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8153 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8154 output_insn_code_cases (output_automata_list_transition_code);
8155 fprintf (output_file, "\n default:\n return -1;\n }\n");
8156 fprintf (output_file, "}\n\n");
8159 /* Output code
8161 if (insn != 0)
8163 insn_code = dfa_insn_code (insn);
8164 if (insn_code > DFA__ADVANCE_CYCLE)
8165 return code;
8167 else
8168 insn_code = DFA__ADVANCE_CYCLE;
8170 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8171 code denotes CODE. */
8172 static void
8173 output_internal_insn_code_evaluation (const char *insn_name,
8174 const char *insn_code_name,
8175 int code)
8177 fprintf (output_file, "\n if (%s == 0)\n", insn_name);
8178 fprintf (output_file, " %s = %s;\n\n",
8179 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8180 if (collapse_flag)
8182 fprintf (output_file, "\n else if (%s == const0_rtx)\n", insn_name);
8183 fprintf (output_file, " %s = %s;\n\n",
8184 insn_code_name, COLLAPSE_NDFA_VALUE_NAME);
8186 fprintf (output_file, "\n else\n {\n");
8187 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8188 DFA_INSN_CODE_FUNC_NAME, insn_name);
8189 fprintf (output_file, " if (%s > %s)\n return %d;\n }\n",
8190 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8194 /* This function outputs `dfa_insn_code' and its helper function
8195 `dfa_insn_code_enlarge'. */
8196 static void
8197 output_dfa_insn_code_func (void)
8199 /* Emacs c-mode gets really confused if there's a { or } in column 0
8200 inside a string, so don't do that. */
8201 fprintf (output_file, "\
8202 static void\n\
8203 dfa_insn_code_enlarge (int uid)\n\
8204 {\n\
8205 int i = %s;\n\
8206 %s = 2 * uid;\n\
8207 %s = XRESIZEVEC (int, %s,\n\
8208 %s);\n\
8209 for (; i < %s; i++)\n\
8210 %s[i] = -1;\n}\n\n",
8211 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8212 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8213 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8214 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8215 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8216 DFA_INSN_CODES_VARIABLE_NAME);
8217 fprintf (output_file, "\
8218 static inline int\n%s (rtx %s)\n\
8219 {\n\
8220 int uid = INSN_UID (%s);\n\
8221 int %s;\n\n",
8222 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8223 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8225 fprintf (output_file,
8226 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8227 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8228 fprintf (output_file, " %s = %s[uid];\n",
8229 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8230 fprintf (output_file, "\
8231 if (%s < 0)\n\
8232 {\n\
8233 %s = %s (%s);\n\
8234 %s[uid] = %s;\n\
8235 }\n",
8236 INTERNAL_INSN_CODE_NAME,
8237 INTERNAL_INSN_CODE_NAME,
8238 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8239 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8240 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8243 /* The function outputs PHR interface function `state_transition'. */
8244 static void
8245 output_trans_func (void)
8247 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8248 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8249 INSN_PARAMETER_NAME);
8250 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8251 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8252 INTERNAL_INSN_CODE_NAME, -1);
8253 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8254 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8257 /* Output function `min_issue_delay'. */
8258 static void
8259 output_min_issue_delay_func (void)
8261 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8262 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8263 INSN_PARAMETER_NAME);
8264 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8265 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8266 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8267 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8268 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8269 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8270 fprintf (output_file, " }\n else\n %s = %s;\n",
8271 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8272 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8273 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8274 CHIP_NAME, STATE_NAME);
8275 fprintf (output_file, "}\n\n");
8278 /* Output function `internal_dead_lock'. */
8279 static void
8280 output_internal_dead_lock_func (void)
8282 automaton_t automaton;
8284 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8285 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8286 fprintf (output_file, "{\n");
8287 for (automaton = description->first_automaton;
8288 automaton != NULL;
8289 automaton = automaton->next_automaton)
8290 if (automaton->locked_states)
8292 fprintf (output_file, " if (");
8293 output_dead_lock_vect_name (output_file, automaton);
8294 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8295 output_chip_member_name (output_file, automaton);
8296 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8298 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8301 /* The function outputs PHR interface function `state_dead_lock_p'. */
8302 static void
8303 output_dead_lock_func (void)
8305 fprintf (output_file, "int\n%s (%s %s)\n",
8306 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8307 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8308 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8311 /* Output function `internal_reset'. */
8312 static void
8313 output_internal_reset_func (void)
8315 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8316 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8317 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8318 CHIP_PARAMETER_NAME, CHIP_NAME);
8321 /* The function outputs PHR interface function `state_size'. */
8322 static void
8323 output_size_func (void)
8325 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8326 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8329 /* The function outputs PHR interface function `state_reset'. */
8330 static void
8331 output_reset_func (void)
8333 fprintf (output_file, "void\n%s (%s %s)\n",
8334 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8335 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8336 CHIP_NAME, STATE_NAME);
8339 /* Output function `min_insn_conflict_delay'. */
8340 static void
8341 output_min_insn_conflict_delay_func (void)
8343 fprintf (output_file,
8344 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8345 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8346 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8347 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8348 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8349 INTERNAL_INSN2_CODE_NAME);
8350 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8351 INTERNAL_INSN_CODE_NAME, 0);
8352 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8353 INTERNAL_INSN2_CODE_NAME, 0);
8354 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8355 CHIP_NAME, STATE_NAME, CHIP_NAME);
8356 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8357 fprintf (output_file, " transition = %s (%s, &%s);\n",
8358 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8359 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8360 fprintf (output_file, " return %s (%s, &%s);\n",
8361 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8362 CHIP_NAME);
8363 fprintf (output_file, "}\n\n");
8366 /* Output the array holding default latency values. These are used in
8367 insn_latency and maximal_insn_latency function implementations. */
8368 static void
8369 output_default_latencies (void)
8371 int i, j, col;
8372 decl_t decl;
8373 const char *tabletype = "unsigned char";
8375 /* Find the smallest integer type that can hold all the default
8376 latency values. */
8377 for (i = 0; i < description->decls_num; i++)
8378 if (description->decls[i]->mode == dm_insn_reserv)
8380 decl = description->decls[i];
8381 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8382 && tabletype[0] != 'i') /* Don't shrink it. */
8383 tabletype = "unsigned short";
8384 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8385 tabletype = "int";
8388 fprintf (output_file, " static const %s default_latencies[] =\n {",
8389 tabletype);
8391 for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
8392 if (description->decls[i]->mode == dm_insn_reserv)
8394 if ((col = (col+1) % 8) == 0)
8395 fputs ("\n ", output_file);
8396 decl = description->decls[i];
8397 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8398 fprintf (output_file, "% 4d,",
8399 DECL_INSN_RESERV (decl)->default_latency);
8401 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8402 fputs ("\n };\n", output_file);
8405 /* Output function `internal_insn_latency'. */
8406 static void
8407 output_internal_insn_latency_func (void)
8409 int i;
8410 decl_t decl;
8411 struct bypass_decl *bypass;
8413 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",
8414 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8415 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8416 INSN2_PARAMETER_NAME);
8417 fprintf (output_file, "{\n");
8419 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8421 fputs (" return 0;\n}\n\n", output_file);
8422 return;
8425 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8426 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8427 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8429 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8430 for (i = 0; i < description->decls_num; i++)
8431 if (description->decls[i]->mode == dm_insn_reserv
8432 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8434 decl = description->decls [i];
8435 fprintf (output_file,
8436 " case %d:\n switch (%s)\n {\n",
8437 DECL_INSN_RESERV (decl)->insn_num,
8438 INTERNAL_INSN2_CODE_NAME);
8439 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8440 bypass != NULL;
8441 bypass = bypass->next)
8443 gcc_assert (bypass->in_insn_reserv->insn_num
8444 != (DECL_INSN_RESERV
8445 (advance_cycle_insn_decl)->insn_num));
8446 fprintf (output_file, " case %d:\n",
8447 bypass->in_insn_reserv->insn_num);
8448 for (;;)
8450 if (bypass->bypass_guard_name == NULL)
8452 gcc_assert (bypass->next == NULL
8453 || (bypass->in_insn_reserv
8454 != bypass->next->in_insn_reserv));
8455 fprintf (output_file, " return %d;\n",
8456 bypass->latency);
8458 else
8460 fprintf (output_file,
8461 " if (%s (%s, %s))\n",
8462 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8463 INSN2_PARAMETER_NAME);
8464 fprintf (output_file, " return %d;\n",
8465 bypass->latency);
8467 if (bypass->next == NULL
8468 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8469 break;
8470 bypass = bypass->next;
8472 if (bypass->bypass_guard_name != NULL)
8473 fprintf (output_file, " break;\n");
8475 fputs (" }\n break;\n", output_file);
8478 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8479 INTERNAL_INSN_CODE_NAME);
8482 /* Output function `internal_maximum_insn_latency'. */
8483 static void
8484 output_internal_maximal_insn_latency_func (void)
8486 decl_t decl;
8487 struct bypass_decl *bypass;
8488 int i;
8489 int max;
8491 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8492 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8493 INSN_PARAMETER_NAME);
8494 fprintf (output_file, "{\n");
8496 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8498 fputs (" return 0;\n}\n\n", output_file);
8499 return;
8502 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8503 for (i = 0; i < description->decls_num; i++)
8504 if (description->decls[i]->mode == dm_insn_reserv
8505 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8507 decl = description->decls [i];
8508 max = DECL_INSN_RESERV (decl)->default_latency;
8509 fprintf (output_file,
8510 " case %d: {",
8511 DECL_INSN_RESERV (decl)->insn_num);
8512 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8513 bypass != NULL;
8514 bypass = bypass->next)
8516 if (bypass->latency > max)
8517 max = bypass->latency;
8519 fprintf (output_file, " return %d; }\n break;\n", max);
8522 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8523 INTERNAL_INSN_CODE_NAME);
8526 /* The function outputs PHR interface function `insn_latency'. */
8527 static void
8528 output_insn_latency_func (void)
8530 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8531 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8532 fprintf (output_file, "{\n int %s, %s;\n",
8533 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8534 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8535 INTERNAL_INSN_CODE_NAME, 0);
8536 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8537 INTERNAL_INSN2_CODE_NAME, 0);
8538 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8539 INTERNAL_INSN_LATENCY_FUNC_NAME,
8540 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8541 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8544 /* The function outputs PHR interface function `maximal_insn_latency'. */
8545 static void
8546 output_maximal_insn_latency_func (void)
8548 fprintf (output_file, "int\n%s (rtx %s)\n",
8549 "maximal_insn_latency", INSN_PARAMETER_NAME);
8550 fprintf (output_file, "{\n int %s;\n",
8551 INTERNAL_INSN_CODE_NAME);
8552 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8553 INTERNAL_INSN_CODE_NAME, 0);
8554 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8555 "internal_maximal_insn_latency",
8556 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8559 /* The function outputs PHR interface function `print_reservation'. */
8560 static void
8561 output_print_reservation_func (void)
8563 decl_t decl;
8564 int i, j;
8566 fprintf (output_file,
8567 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8568 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8569 INSN_PARAMETER_NAME);
8571 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8573 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8574 NOTHING_NAME, FILE_PARAMETER_NAME);
8575 return;
8579 fputs (" static const char *const reservation_names[] =\n {",
8580 output_file);
8582 for (i = 0, j = 0; i < description->normal_decls_num; i++)
8584 decl = description->decls [i];
8585 if (decl->mode == dm_insn_reserv)
8587 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8588 j++;
8590 fprintf (output_file, "\n \"%s\",",
8591 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8592 finish_regexp_representation ();
8595 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8597 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8598 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8600 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8601 INSN_PARAMETER_NAME,
8602 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8603 fprintf (output_file, " else\n\
8604 {\n\
8605 %s = %s (%s);\n\
8606 if (%s > %s)\n\
8607 %s = %s;\n\
8608 }\n",
8609 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8610 INSN_PARAMETER_NAME,
8611 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8612 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8614 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8615 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8618 /* The following function is used to sort unit declaration by their
8619 names. */
8620 static int
8621 units_cmp (const void *unit1, const void *unit2)
8623 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8624 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8626 return strcmp (u1->name, u2->name);
8629 /* The following macro value is name of struct containing unit name
8630 and unit code. */
8631 #define NAME_CODE_STRUCT_NAME "name_code"
8633 /* The following macro value is name of table of struct name_code. */
8634 #define NAME_CODE_TABLE_NAME "name_code_table"
8636 /* The following macro values are member names for struct name_code. */
8637 #define NAME_MEMBER_NAME "name"
8638 #define CODE_MEMBER_NAME "code"
8640 /* The following macro values are local variable names for function
8641 `get_cpu_unit_code'. */
8642 #define CMP_VARIABLE_NAME "cmp"
8643 #define LOW_VARIABLE_NAME "l"
8644 #define MIDDLE_VARIABLE_NAME "m"
8645 #define HIGH_VARIABLE_NAME "h"
8647 /* The following function outputs function to obtain internal cpu unit
8648 code by the cpu unit name. */
8649 static void
8650 output_get_cpu_unit_code_func (void)
8652 int i;
8653 unit_decl_t *units;
8655 fprintf (output_file, "int\n%s (const char *%s)\n",
8656 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8657 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8658 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8659 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8660 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8661 fprintf (output_file, " static struct %s %s [] =\n {\n",
8662 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8663 units = XNEWVEC (unit_decl_t, description->units_num);
8664 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8665 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8666 for (i = 0; i < description->units_num; i++)
8667 if (units [i]->query_p)
8668 fprintf (output_file, " {\"%s\", %d},\n",
8669 units[i]->name, units[i]->query_num);
8670 fprintf (output_file, " };\n\n");
8671 fprintf (output_file, " /* The following is binary search: */\n");
8672 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8673 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8674 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8675 fprintf (output_file, " while (%s <= %s)\n {\n",
8676 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8677 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8678 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8679 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8680 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8681 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8682 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8683 fprintf (output_file, " %s = %s - 1;\n",
8684 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8685 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8686 fprintf (output_file, " %s = %s + 1;\n",
8687 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8688 fprintf (output_file, " else\n");
8689 fprintf (output_file, " return %s [%s].%s;\n }\n",
8690 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8691 fprintf (output_file, " return -1;\n}\n\n");
8692 free (units);
8695 /* The following function outputs function to check reservation of cpu
8696 unit (its internal code will be passed as the function argument) in
8697 given cpu state. */
8698 static void
8699 output_cpu_unit_reservation_p (void)
8701 automaton_t automaton;
8703 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8704 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8705 STATE_TYPE_NAME, STATE_NAME,
8706 CPU_CODE_PARAMETER_NAME);
8707 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8708 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8709 description->query_units_num);
8710 if (description->query_units_num > 0)
8711 for (automaton = description->first_automaton;
8712 automaton != NULL;
8713 automaton = automaton->next_automaton)
8715 fprintf (output_file, " if ((");
8716 output_reserved_units_table_name (output_file, automaton);
8717 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8718 output_chip_member_name (output_file, automaton);
8719 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8720 (description->query_units_num + 7) / 8,
8721 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8722 fprintf (output_file, " return 1;\n");
8724 fprintf (output_file, " return 0;\n}\n\n");
8727 /* The following function outputs a function to check if insn
8728 has a dfa reservation. */
8729 static void
8730 output_insn_has_dfa_reservation_p (void)
8732 fprintf (output_file,
8733 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8734 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8735 INSN_PARAMETER_NAME);
8737 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8739 fprintf (output_file, " return false;\n}\n\n");
8740 return;
8743 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8745 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8746 INSN_PARAMETER_NAME,
8747 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8748 fprintf (output_file, " else\n\
8749 {\n\
8750 %s = %s (%s);\n\
8751 if (%s > %s)\n\
8752 %s = %s;\n\
8753 }\n\n",
8754 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8755 INSN_PARAMETER_NAME,
8756 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8757 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8759 fprintf (output_file, " return %s != %s;\n}\n\n",
8760 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8763 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8764 and 'dfa_clear_single_insn_cache'. */
8765 static void
8766 output_dfa_clean_insn_cache_func (void)
8768 fprintf (output_file,
8769 "void\n%s (void)\n{\n int %s;\n\n",
8770 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8771 fprintf (output_file,
8772 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8773 I_VARIABLE_NAME, I_VARIABLE_NAME,
8774 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8775 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8777 fprintf (output_file,
8778 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8779 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8780 I_VARIABLE_NAME);
8781 fprintf (output_file,
8782 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8783 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8784 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8785 I_VARIABLE_NAME);
8788 /* The function outputs PHR interface function `dfa_start'. */
8789 static void
8790 output_dfa_start_func (void)
8792 fprintf (output_file,
8793 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8794 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8795 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8796 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8797 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8800 /* The function outputs PHR interface function `dfa_finish'. */
8801 static void
8802 output_dfa_finish_func (void)
8804 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8805 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8810 /* The page contains code for output description file (readable
8811 representation of original description and generated DFA(s). */
8813 /* The function outputs string representation of IR reservation. */
8814 static void
8815 output_regexp (regexp_t regexp)
8817 fprintf (output_description_file, "%s", regexp_representation (regexp));
8818 finish_regexp_representation ();
8821 /* Output names of units in LIST separated by comma. */
8822 static void
8823 output_unit_set_el_list (unit_set_el_t list)
8825 unit_set_el_t el;
8827 for (el = list; el != NULL; el = el->next_unit_set_el)
8829 if (el != list)
8830 fprintf (output_description_file, ", ");
8831 fprintf (output_description_file, "%s", el->unit_decl->name);
8835 /* Output patterns in LIST separated by comma. */
8836 static void
8837 output_pattern_set_el_list (pattern_set_el_t list)
8839 pattern_set_el_t el;
8840 int i;
8842 for (el = list; el != NULL; el = el->next_pattern_set_el)
8844 if (el != list)
8845 fprintf (output_description_file, ", ");
8846 for (i = 0; i < el->units_num; i++)
8847 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8848 el->unit_decls [i]->name);
8852 /* The function outputs string representation of IR define_reservation
8853 and define_insn_reservation. */
8854 static void
8855 output_description (void)
8857 decl_t decl;
8858 int i;
8860 for (i = 0; i < description->decls_num; i++)
8862 decl = description->decls [i];
8863 if (decl->mode == dm_unit)
8865 if (DECL_UNIT (decl)->excl_list != NULL)
8867 fprintf (output_description_file, "unit %s exclusion_set: ",
8868 DECL_UNIT (decl)->name);
8869 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8870 fprintf (output_description_file, "\n");
8872 if (DECL_UNIT (decl)->presence_list != NULL)
8874 fprintf (output_description_file, "unit %s presence_set: ",
8875 DECL_UNIT (decl)->name);
8876 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8877 fprintf (output_description_file, "\n");
8879 if (DECL_UNIT (decl)->final_presence_list != NULL)
8881 fprintf (output_description_file, "unit %s final_presence_set: ",
8882 DECL_UNIT (decl)->name);
8883 output_pattern_set_el_list
8884 (DECL_UNIT (decl)->final_presence_list);
8885 fprintf (output_description_file, "\n");
8887 if (DECL_UNIT (decl)->absence_list != NULL)
8889 fprintf (output_description_file, "unit %s absence_set: ",
8890 DECL_UNIT (decl)->name);
8891 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8892 fprintf (output_description_file, "\n");
8894 if (DECL_UNIT (decl)->final_absence_list != NULL)
8896 fprintf (output_description_file, "unit %s final_absence_set: ",
8897 DECL_UNIT (decl)->name);
8898 output_pattern_set_el_list
8899 (DECL_UNIT (decl)->final_absence_list);
8900 fprintf (output_description_file, "\n");
8904 fprintf (output_description_file, "\n");
8905 for (i = 0; i < description->normal_decls_num; i++)
8907 decl = description->decls [i];
8908 if (decl->mode == dm_reserv)
8910 fprintf (output_description_file, "reservation %s: ",
8911 DECL_RESERV (decl)->name);
8912 output_regexp (DECL_RESERV (decl)->regexp);
8913 fprintf (output_description_file, "\n");
8915 else if (decl->mode == dm_insn_reserv)
8917 fprintf (output_description_file, "insn reservation %s ",
8918 DECL_INSN_RESERV (decl)->name);
8919 print_rtl (output_description_file,
8920 DECL_INSN_RESERV (decl)->condexp);
8921 fprintf (output_description_file, ": ");
8922 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8923 fprintf (output_description_file, "\n");
8925 else if (decl->mode == dm_bypass)
8926 fprintf (output_description_file, "bypass %d %s %s\n",
8927 DECL_BYPASS (decl)->latency,
8928 DECL_BYPASS (decl)->out_pattern,
8929 DECL_BYPASS (decl)->in_pattern);
8931 fprintf (output_description_file, "\n\f\n");
8934 /* The function outputs name of AUTOMATON. */
8935 static void
8936 output_automaton_name (FILE *f, automaton_t automaton)
8938 if (automaton->corresponding_automaton_decl == NULL)
8939 fprintf (f, "#%d", automaton->automaton_order_num);
8940 else
8941 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8944 /* Maximal length of line for pretty printing into description
8945 file. */
8946 #define MAX_LINE_LENGTH 70
8948 /* The function outputs units name belonging to AUTOMATON. */
8949 static void
8950 output_automaton_units (automaton_t automaton)
8952 decl_t decl;
8953 const char *name;
8954 int curr_line_length;
8955 int there_is_an_automaton_unit;
8956 int i;
8958 fprintf (output_description_file, "\n Corresponding units:\n");
8959 fprintf (output_description_file, " ");
8960 curr_line_length = 4;
8961 there_is_an_automaton_unit = 0;
8962 for (i = 0; i < description->decls_num; i++)
8964 decl = description->decls [i];
8965 if (decl->mode == dm_unit
8966 && (DECL_UNIT (decl)->corresponding_automaton_num
8967 == automaton->automaton_order_num))
8969 there_is_an_automaton_unit = 1;
8970 name = DECL_UNIT (decl)->name;
8971 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8973 curr_line_length = strlen (name) + 4;
8974 fprintf (output_description_file, "\n ");
8976 else
8978 curr_line_length += strlen (name) + 1;
8979 fprintf (output_description_file, " ");
8981 fprintf (output_description_file, "%s", name);
8984 if (!there_is_an_automaton_unit)
8985 fprintf (output_description_file, "<None>");
8986 fprintf (output_description_file, "\n\n");
8989 /* The following variable is used for forming array of all possible cpu unit
8990 reservations described by the current DFA state. */
8991 static VEC(reserv_sets_t, heap) *state_reservs;
8993 /* The function forms `state_reservs' for STATE. */
8994 static void
8995 add_state_reservs (state_t state)
8997 alt_state_t curr_alt_state;
8999 if (state->component_states != NULL)
9000 for (curr_alt_state = state->component_states;
9001 curr_alt_state != NULL;
9002 curr_alt_state = curr_alt_state->next_sorted_alt_state)
9003 add_state_reservs (curr_alt_state->state);
9004 else
9005 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
9008 /* The function outputs readable representation of all out arcs of
9009 STATE. */
9010 static void
9011 output_state_arcs (state_t state)
9013 arc_t arc;
9014 ainsn_t ainsn;
9015 const char *insn_name;
9016 int curr_line_length;
9018 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9020 ainsn = arc->insn;
9021 gcc_assert (ainsn->first_insn_with_same_reservs);
9022 fprintf (output_description_file, " ");
9023 curr_line_length = 7;
9024 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9027 insn_name = ainsn->insn_reserv_decl->name;
9028 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9030 if (ainsn != arc->insn)
9032 fprintf (output_description_file, ",\n ");
9033 curr_line_length = strlen (insn_name) + 6;
9035 else
9036 curr_line_length += strlen (insn_name);
9038 else
9040 curr_line_length += strlen (insn_name);
9041 if (ainsn != arc->insn)
9043 curr_line_length += 2;
9044 fprintf (output_description_file, ", ");
9047 fprintf (output_description_file, "%s", insn_name);
9048 ainsn = ainsn->next_same_reservs_insn;
9050 while (ainsn != NULL);
9051 fprintf (output_description_file, " %d \n",
9052 arc->to_state->order_state_num);
9054 fprintf (output_description_file, "\n");
9057 /* The following function is used for sorting possible cpu unit
9058 reservation of a DFA state. */
9059 static int
9060 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9062 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
9063 *(const_reserv_sets_t const*) reservs_ptr_2);
9066 /* The following function is used for sorting possible cpu unit
9067 reservation of a DFA state. */
9068 static void
9069 remove_state_duplicate_reservs (void)
9071 size_t i, j;
9073 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
9074 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
9075 VEC_index (reserv_sets_t, state_reservs, i)))
9077 j++;
9078 VEC_replace (reserv_sets_t, state_reservs, j,
9079 VEC_index (reserv_sets_t, state_reservs, i));
9081 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
9084 /* The following function output readable representation of DFA(s)
9085 state used for fast recognition of pipeline hazards. State is
9086 described by possible (current and scheduled) cpu unit
9087 reservations. */
9088 static void
9089 output_state (state_t state)
9091 size_t i;
9093 state_reservs = 0;
9095 fprintf (output_description_file, " State #%d", state->order_state_num);
9096 fprintf (output_description_file,
9097 state->new_cycle_p ? " (new cycle)\n" : "\n");
9098 add_state_reservs (state);
9099 VEC_qsort (reserv_sets_t, state_reservs, state_reservs_cmp);
9100 remove_state_duplicate_reservs ();
9101 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
9103 fprintf (output_description_file, " ");
9104 output_reserv_sets (output_description_file,
9105 VEC_index (reserv_sets_t, state_reservs, i));
9106 fprintf (output_description_file, "\n");
9108 fprintf (output_description_file, "\n");
9109 output_state_arcs (state);
9110 VEC_free (reserv_sets_t, heap, state_reservs);
9113 /* The following function output readable representation of
9114 DFAs used for fast recognition of pipeline hazards. */
9115 static void
9116 output_automaton_descriptions (void)
9118 automaton_t automaton;
9120 for (automaton = description->first_automaton;
9121 automaton != NULL;
9122 automaton = automaton->next_automaton)
9124 fprintf (output_description_file, "\nAutomaton ");
9125 output_automaton_name (output_description_file, automaton);
9126 fprintf (output_description_file, "\n");
9127 output_automaton_units (automaton);
9128 pass_states (automaton, output_state);
9134 /* The page contains top level function for generation DFA(s) used for
9135 PHR. */
9137 /* The function outputs statistics about work of different phases of
9138 DFA generator. */
9139 static void
9140 output_statistics (FILE *f)
9142 automaton_t automaton;
9143 int states_num;
9144 #ifndef NDEBUG
9145 int transition_comb_vect_els = 0;
9146 int transition_full_vect_els = 0;
9147 int min_issue_delay_vect_els = 0;
9148 int locked_states = 0;
9149 #endif
9151 for (automaton = description->first_automaton;
9152 automaton != NULL;
9153 automaton = automaton->next_automaton)
9155 fprintf (f, "\nAutomaton ");
9156 output_automaton_name (f, automaton);
9157 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9158 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9159 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9160 automaton->DFA_states_num, automaton->DFA_arcs_num);
9161 states_num = automaton->DFA_states_num;
9162 if (!no_minimization_flag)
9164 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9165 automaton->minimal_DFA_states_num,
9166 automaton->minimal_DFA_arcs_num);
9167 states_num = automaton->minimal_DFA_states_num;
9169 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9170 description->insns_num, automaton->insn_equiv_classes_num);
9171 fprintf (f, " %d locked states\n", automaton->locked_states);
9172 #ifndef NDEBUG
9173 fprintf
9174 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9175 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9176 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9177 (comb_vect_p (automaton->trans_table)
9178 ? "use comb vect" : "use simple vect"));
9179 fprintf
9180 (f, "%5ld min delay table els, compression factor %d\n",
9181 (long) states_num * automaton->insn_equiv_classes_num,
9182 automaton->min_issue_delay_table_compression_factor);
9183 transition_comb_vect_els
9184 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9185 transition_full_vect_els
9186 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9187 min_issue_delay_vect_els
9188 += states_num * automaton->insn_equiv_classes_num;
9189 locked_states
9190 += automaton->locked_states;
9191 #endif
9193 #ifndef NDEBUG
9194 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9195 allocated_states_num, allocated_arcs_num);
9196 fprintf (f, "%5d all allocated alternative states\n",
9197 allocated_alt_states_num);
9198 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9199 transition_comb_vect_els, transition_full_vect_els);
9200 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9201 fprintf (f, "%5d all locked states\n", locked_states);
9202 #endif
9205 /* The function output times of work of different phases of DFA
9206 generator. */
9207 static void
9208 output_time_statistics (FILE *f)
9210 fprintf (f, "\n transformation: ");
9211 print_active_time (f, transform_time);
9212 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9213 print_active_time (f, NDFA_time);
9214 if (ndfa_flag)
9216 fprintf (f, ", NDFA -> DFA: ");
9217 print_active_time (f, NDFA_to_DFA_time);
9219 fprintf (f, "\n DFA minimization: ");
9220 print_active_time (f, minimize_time);
9221 fprintf (f, ", making insn equivalence: ");
9222 print_active_time (f, equiv_time);
9223 fprintf (f, "\n all automaton generation: ");
9224 print_active_time (f, automaton_generation_time);
9225 fprintf (f, ", output: ");
9226 print_active_time (f, output_time);
9227 fprintf (f, "\n");
9230 /* The function generates DFA (deterministic finite state automaton)
9231 for fast recognition of pipeline hazards. No errors during
9232 checking must be fixed before this function call. */
9233 static void
9234 generate (void)
9236 automata_num = split_argument;
9237 if (description->units_num < automata_num)
9238 automata_num = description->units_num;
9239 initiate_states ();
9240 initiate_arcs ();
9241 initiate_automata_lists ();
9242 initiate_pass_states ();
9243 initiate_excl_sets ();
9244 initiate_presence_absence_pattern_sets ();
9245 automaton_generation_time = create_ticker ();
9246 create_automata ();
9247 ticker_off (&automaton_generation_time);
9252 /* This page mainly contains top level functions of pipeline hazards
9253 description translator. */
9255 /* The following macro value is suffix of name of description file of
9256 pipeline hazards description translator. */
9257 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9259 /* The function returns suffix of given file name. The returned
9260 string can not be changed. */
9261 static const char *
9262 file_name_suffix (const char *file_name)
9264 const char *last_period;
9266 for (last_period = NULL; *file_name != '\0'; file_name++)
9267 if (*file_name == '.')
9268 last_period = file_name;
9269 return (last_period == NULL ? file_name : last_period);
9272 /* The function returns base name of given file name, i.e. pointer to
9273 first char after last `/' (or `\' for WIN32) in given file name,
9274 given file name itself if the directory name is absent. The
9275 returned string can not be changed. */
9276 static const char *
9277 base_file_name (const char *file_name)
9279 int directory_name_length;
9281 directory_name_length = strlen (file_name);
9282 #ifdef WIN32
9283 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9284 && file_name[directory_name_length] != '\\')
9285 #else
9286 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9287 #endif
9288 directory_name_length--;
9289 return file_name + directory_name_length + 1;
9292 /* A function passed as argument to init_rtx_reader_args_cb. It parses the
9293 options available for genautomata. Returns true if the option was
9294 recognized. */
9295 static bool
9296 parse_automata_opt (const char *str)
9298 if (strcmp (str, NO_MINIMIZATION_OPTION) == 0)
9299 no_minimization_flag = 1;
9300 else if (strcmp (str, TIME_OPTION) == 0)
9301 time_flag = 1;
9302 else if (strcmp (str, STATS_OPTION) == 0)
9303 stats_flag = 1;
9304 else if (strcmp (str, V_OPTION) == 0)
9305 v_flag = 1;
9306 else if (strcmp (str, W_OPTION) == 0)
9307 w_flag = 1;
9308 else if (strcmp (str, NDFA_OPTION) == 0)
9309 ndfa_flag = 1;
9310 else if (strcmp (str, COLLAPSE_OPTION) == 0)
9311 collapse_flag = 1;
9312 else if (strcmp (str, PROGRESS_OPTION) == 0)
9313 progress_flag = 1;
9314 else if (strcmp (str, "-split") == 0)
9316 fatal ("option `-split' has not been implemented yet\n");
9317 /* split_argument = atoi (argument_vect [i + 1]); */
9319 else
9320 return false;
9322 return true;
9325 /* The following is top level function to initialize the work of
9326 pipeline hazards description translator. */
9327 static void
9328 initiate_automaton_gen (char **argv)
9330 const char *base_name;
9332 /* Initialize IR storage. */
9333 obstack_init (&irp);
9334 initiate_automaton_decl_table ();
9335 initiate_insn_decl_table ();
9336 initiate_decl_table ();
9337 output_file = stdout;
9338 output_description_file = NULL;
9339 base_name = base_file_name (argv[1]);
9340 obstack_grow (&irp, base_name,
9341 strlen (base_name) - strlen (file_name_suffix (base_name)));
9342 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9343 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9344 obstack_1grow (&irp, '\0');
9345 output_description_file_name = obstack_base (&irp);
9346 obstack_finish (&irp);
9349 /* The following function checks existence at least one arc marked by
9350 each insn. */
9351 static void
9352 check_automata_insn_issues (void)
9354 automaton_t automaton;
9355 ainsn_t ainsn, reserv_ainsn;
9357 for (automaton = description->first_automaton;
9358 automaton != NULL;
9359 automaton = automaton->next_automaton)
9361 for (ainsn = automaton->ainsn_list;
9362 ainsn != NULL;
9363 ainsn = ainsn->next_ainsn)
9364 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
9365 && ainsn != automaton->collapse_ainsn)
9367 for (reserv_ainsn = ainsn;
9368 reserv_ainsn != NULL;
9369 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9370 if (automaton->corresponding_automaton_decl != NULL)
9372 if (!w_flag)
9373 error ("Automaton `%s': Insn `%s' will never be issued",
9374 automaton->corresponding_automaton_decl->name,
9375 reserv_ainsn->insn_reserv_decl->name);
9376 else
9377 warning ("Automaton `%s': Insn `%s' will never be issued",
9378 automaton->corresponding_automaton_decl->name,
9379 reserv_ainsn->insn_reserv_decl->name);
9381 else
9383 if (!w_flag)
9384 error ("Insn `%s' will never be issued",
9385 reserv_ainsn->insn_reserv_decl->name);
9386 else
9387 warning ("Insn `%s' will never be issued",
9388 reserv_ainsn->insn_reserv_decl->name);
9394 /* The following vla is used for storing pointers to all achieved
9395 states. */
9396 static VEC(state_t, heap) *automaton_states;
9398 /* This function is called by function pass_states to add an achieved
9399 STATE. */
9400 static void
9401 add_automaton_state (state_t state)
9403 VEC_safe_push (state_t, heap, automaton_states, state);
9406 /* The following function forms list of important automata (whose
9407 states may be changed after the insn issue) for each insn. */
9408 static void
9409 form_important_insn_automata_lists (void)
9411 automaton_t automaton;
9412 decl_t decl;
9413 ainsn_t ainsn;
9414 arc_t arc;
9415 int i;
9416 size_t n;
9418 automaton_states = 0;
9419 /* Mark important ainsns. */
9420 for (automaton = description->first_automaton;
9421 automaton != NULL;
9422 automaton = automaton->next_automaton)
9424 VEC_truncate (state_t, automaton_states, 0);
9425 pass_states (automaton, add_automaton_state);
9426 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9428 state_t s = VEC_index (state_t, automaton_states, n);
9429 for (arc = first_out_arc (s);
9430 arc != NULL;
9431 arc = next_out_arc (arc))
9432 if (arc->to_state != s)
9434 gcc_assert (arc->insn->first_insn_with_same_reservs);
9435 for (ainsn = arc->insn;
9436 ainsn != NULL;
9437 ainsn = ainsn->next_same_reservs_insn)
9438 ainsn->important_p = TRUE;
9442 VEC_free (state_t, heap, automaton_states);
9444 /* Create automata sets for the insns. */
9445 for (i = 0; i < description->decls_num; i++)
9447 decl = description->decls [i];
9448 if (decl->mode == dm_insn_reserv)
9450 automata_list_start ();
9451 for (automaton = description->first_automaton;
9452 automaton != NULL;
9453 automaton = automaton->next_automaton)
9454 for (ainsn = automaton->ainsn_list;
9455 ainsn != NULL;
9456 ainsn = ainsn->next_ainsn)
9457 if (ainsn->important_p
9458 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9460 automata_list_add (automaton);
9461 break;
9463 DECL_INSN_RESERV (decl)->important_automata_list
9464 = automata_list_finish ();
9470 /* The following is top level function to generate automat(a,on) for
9471 fast recognition of pipeline hazards. */
9472 static void
9473 expand_automata (void)
9475 int i;
9477 description = XCREATENODEVAR (struct description,
9478 sizeof (struct description)
9479 /* Two entries for special insns. */
9480 + sizeof (decl_t) * (VEC_length (decl_t, decls) + 1));
9481 description->decls_num = VEC_length (decl_t, decls);
9482 description->normal_decls_num = description->decls_num;
9483 description->query_units_num = 0;
9484 for (i = 0; i < description->decls_num; i++)
9486 description->decls [i] = VEC_index (decl_t, decls, i);
9487 if (description->decls [i]->mode == dm_unit
9488 && DECL_UNIT (description->decls [i])->query_p)
9489 DECL_UNIT (description->decls [i])->query_num
9490 = description->query_units_num++;
9492 all_time = create_ticker ();
9493 check_time = create_ticker ();
9494 if (progress_flag)
9495 fprintf (stderr, "Check description...");
9496 check_all_description ();
9497 if (progress_flag)
9498 fprintf (stderr, "done\n");
9499 ticker_off (&check_time);
9500 generation_time = create_ticker ();
9501 if (!have_error)
9503 transform_insn_regexps ();
9504 check_unit_distributions_to_automata ();
9506 if (!have_error)
9508 generate ();
9509 check_automata_insn_issues ();
9511 if (!have_error)
9513 form_important_insn_automata_lists ();
9515 ticker_off (&generation_time);
9518 /* The following is top level function to output PHR and to finish
9519 work with pipeline description translator. */
9520 static void
9521 write_automata (void)
9523 output_time = create_ticker ();
9524 if (progress_flag)
9525 fprintf (stderr, "Forming and outputting automata tables...");
9526 output_tables ();
9527 if (progress_flag)
9529 fprintf (stderr, "done\n");
9530 fprintf (stderr, "Output functions to work with automata...");
9532 output_chip_definitions ();
9533 output_max_insn_queue_index_def ();
9534 output_internal_min_issue_delay_func ();
9535 output_internal_trans_func ();
9536 /* Cache of insn dfa codes: */
9537 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9538 fprintf (output_file, "\nstatic int %s;\n\n",
9539 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9540 output_dfa_insn_code_func ();
9541 output_trans_func ();
9542 output_min_issue_delay_func ();
9543 output_internal_dead_lock_func ();
9544 output_dead_lock_func ();
9545 output_size_func ();
9546 output_internal_reset_func ();
9547 output_reset_func ();
9548 output_min_insn_conflict_delay_func ();
9549 output_default_latencies ();
9550 output_internal_insn_latency_func ();
9551 output_insn_latency_func ();
9552 output_internal_maximal_insn_latency_func ();
9553 output_maximal_insn_latency_func ();
9554 output_print_reservation_func ();
9555 /* Output function get_cpu_unit_code. */
9556 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9557 output_get_cpu_unit_code_func ();
9558 output_cpu_unit_reservation_p ();
9559 output_insn_has_dfa_reservation_p ();
9560 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9561 CPU_UNITS_QUERY_MACRO_NAME);
9562 output_dfa_clean_insn_cache_func ();
9563 output_dfa_start_func ();
9564 output_dfa_finish_func ();
9565 if (progress_flag)
9566 fprintf (stderr, "done\n");
9567 if (v_flag)
9569 output_description_file = fopen (output_description_file_name, "w");
9570 if (output_description_file == NULL)
9572 perror (output_description_file_name);
9573 exit (FATAL_EXIT_CODE);
9575 if (progress_flag)
9576 fprintf (stderr, "Output automata description...");
9577 output_description ();
9578 output_automaton_descriptions ();
9579 if (progress_flag)
9580 fprintf (stderr, "done\n");
9581 output_statistics (output_description_file);
9583 if (stats_flag)
9584 output_statistics (stderr);
9585 ticker_off (&output_time);
9586 if (time_flag)
9587 output_time_statistics (stderr);
9588 finish_states ();
9589 finish_arcs ();
9590 finish_automata_lists ();
9591 if (time_flag)
9593 fprintf (stderr, "Summary:\n");
9594 fprintf (stderr, " check time ");
9595 print_active_time (stderr, check_time);
9596 fprintf (stderr, ", generation time ");
9597 print_active_time (stderr, generation_time);
9598 fprintf (stderr, ", all time ");
9599 print_active_time (stderr, all_time);
9600 fprintf (stderr, "\n");
9602 /* Finish all work. */
9603 if (output_description_file != NULL)
9605 fflush (output_description_file);
9606 if (ferror (stdout) != 0)
9607 fatal ("Error in writing DFA description file %s: %s",
9608 output_description_file_name, xstrerror (errno));
9609 fclose (output_description_file);
9611 finish_automaton_decl_table ();
9612 finish_insn_decl_table ();
9613 finish_decl_table ();
9614 obstack_free (&irp, NULL);
9615 if (have_error && output_description_file != NULL)
9616 remove (output_description_file_name);
9620 main (int argc, char **argv)
9622 rtx desc;
9624 progname = "genautomata";
9626 if (!init_rtx_reader_args_cb (argc, argv, parse_automata_opt))
9627 return (FATAL_EXIT_CODE);
9629 initiate_automaton_gen (argv);
9630 while (1)
9632 int lineno;
9633 int insn_code_number;
9635 desc = read_md_rtx (&lineno, &insn_code_number);
9636 if (desc == NULL)
9637 break;
9639 switch (GET_CODE (desc))
9641 case DEFINE_CPU_UNIT:
9642 gen_cpu_unit (desc);
9643 break;
9645 case DEFINE_QUERY_CPU_UNIT:
9646 gen_query_cpu_unit (desc);
9647 break;
9649 case DEFINE_BYPASS:
9650 gen_bypass (desc);
9651 break;
9653 case EXCLUSION_SET:
9654 gen_excl_set (desc);
9655 break;
9657 case PRESENCE_SET:
9658 gen_presence_set (desc);
9659 break;
9661 case FINAL_PRESENCE_SET:
9662 gen_final_presence_set (desc);
9663 break;
9665 case ABSENCE_SET:
9666 gen_absence_set (desc);
9667 break;
9669 case FINAL_ABSENCE_SET:
9670 gen_final_absence_set (desc);
9671 break;
9673 case DEFINE_AUTOMATON:
9674 gen_automaton (desc);
9675 break;
9677 case AUTOMATA_OPTION:
9678 gen_automata_option (desc);
9679 break;
9681 case DEFINE_RESERVATION:
9682 gen_reserv (desc);
9683 break;
9685 case DEFINE_INSN_RESERVATION:
9686 gen_insn_reserv (desc);
9687 break;
9689 default:
9690 break;
9694 if (have_error)
9695 return FATAL_EXIT_CODE;
9697 if (VEC_length (decl_t, decls) > 0)
9699 expand_automata ();
9700 if (!have_error)
9702 puts ("/* Generated automatically by the program `genautomata'\n"
9703 " from the machine description file `md'. */\n\n"
9704 "#include \"config.h\"\n"
9705 "#include \"system.h\"\n"
9706 "#include \"coretypes.h\"\n"
9707 "#include \"tm.h\"\n"
9708 "#include \"rtl.h\"\n"
9709 "#include \"tm_p.h\"\n"
9710 "#include \"insn-config.h\"\n"
9711 "#include \"recog.h\"\n"
9712 "#include \"regs.h\"\n"
9713 "#include \"output.h\"\n"
9714 "#include \"insn-attr.h\"\n"
9715 "#include \"diagnostic-core.h\"\n"
9716 "#include \"flags.h\"\n"
9717 "#include \"function.h\"\n"
9718 "#include \"emit-rtl.h\"\n");
9719 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9721 write_automata ();
9724 else
9726 puts ("/* Generated automatically by the program `genautomata'\n"
9727 " from the machine description file `md'. */\n\n"
9728 "/* There is no automaton, but ISO C forbids empty\n"
9729 " translation units, so include a header file with some\n"
9730 " declarations, and its pre-requisite header file. */\n"
9731 "#include \"config.h\"\n"
9732 "#include \"system.h\"\n");
9735 fflush (stdout);
9736 return (ferror (stdout) != 0 || have_error
9737 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);