PR target/50465
[official-gcc.git] / gcc / genautomata.c
blobf331f507dae86bd1138c795f60f39e035cd750c3
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 decribed 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, 0);
5081 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
5082 prev = NULL;
5083 for (curr = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
5084 curr != NULL;
5085 prev = curr, curr = curr->next)
5086 if (curr->unit_decl >= unit_decl)
5087 break;
5088 if (curr != NULL && curr->unit_decl == unit_decl)
5089 return;
5090 obstack_blank (&unit_usages, sizeof (struct unit_usage));
5091 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
5092 obstack_finish (&unit_usages);
5093 unit_usage_ptr->unit_decl = unit_decl;
5094 unit_decl->last_distribution_check_cycle = -1; /* undefined */
5095 unit_usage_ptr->next = curr;
5096 if (prev == NULL)
5097 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
5098 else
5099 prev->next = unit_usage_ptr;
5102 /* Return true if unit UNIT_DECL is present on the LIST. */
5103 static bool
5104 unit_present_on_list_p (unit_usage_t list, unit_decl_t unit_decl)
5106 while (list != NULL)
5108 if (list->unit_decl == unit_decl)
5109 return true;
5110 list = list->next;
5112 return false;
5115 /* The function returns true if reservations of alternatives ALT1 and
5116 ALT2 are equal after excluding reservations of units of
5117 EXCLUDED_AUTOMATON_DECL. */
5118 static bool
5119 equal_alternatives_p (int alt1, int alt2, int n_alts,
5120 struct automaton_decl *excluded_automaton_decl)
5122 int i;
5123 unit_usage_t list1, list2;
5125 for (i = 0;
5126 i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5127 i += n_alts)
5129 for (list1 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt1),
5130 list2 = VEC_index (unit_usage_t, cycle_alt_unit_usages, i + alt2);;
5131 list1 = list1->next, list2 = list2->next)
5133 while (list1 != NULL
5134 && list1->unit_decl->automaton_decl == excluded_automaton_decl)
5135 list1 = list1->next;
5136 while (list2 != NULL
5137 && list2->unit_decl->automaton_decl == excluded_automaton_decl)
5138 list2 = list2->next;
5139 if (list1 == NULL || list2 == NULL)
5141 if (list1 != list2)
5142 return false;
5143 else
5144 break;
5146 if (list1->unit_decl != list2->unit_decl)
5147 return false;
5150 return true;
5153 DEF_VEC_I(int);
5154 DEF_VEC_ALLOC_I(int, heap);
5156 /* The function processes given REGEXP to find units with the wrong
5157 distribution. */
5158 static void
5159 check_regexp_units_distribution (const char *insn_reserv_name,
5160 regexp_t regexp)
5162 int i, j, k, cycle, start, n_alts, alt, alt2;
5163 bool annotation_reservation_message_reported_p;
5164 regexp_t seq, allof, unit;
5165 struct unit_usage *unit_usage_ptr;
5166 VEC(int, heap) *marked;
5168 if (regexp == NULL || regexp->mode != rm_oneof)
5169 return;
5170 /* Store all unit usages in the regexp: */
5171 obstack_init (&unit_usages);
5172 cycle_alt_unit_usages = VEC_alloc (unit_usage_t, heap, 10);
5174 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5176 seq = REGEXP_ONEOF (regexp)->regexps [i];
5177 switch (seq->mode)
5179 case rm_sequence:
5180 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
5182 allof = REGEXP_SEQUENCE (seq)->regexps [j];
5183 switch (allof->mode)
5185 case rm_allof:
5186 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
5188 unit = REGEXP_ALLOF (allof)->regexps [k];
5189 if (unit->mode == rm_unit)
5190 store_alt_unit_usage (regexp, unit, j, i);
5191 else
5192 gcc_assert (unit->mode == rm_nothing);
5194 break;
5196 case rm_unit:
5197 store_alt_unit_usage (regexp, allof, j, i);
5198 break;
5200 case rm_nothing:
5201 break;
5203 default:
5204 gcc_unreachable ();
5207 break;
5209 case rm_allof:
5210 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5212 unit = REGEXP_ALLOF (seq)->regexps [k];
5213 switch (unit->mode)
5215 case rm_unit:
5216 store_alt_unit_usage (regexp, unit, 0, i);
5217 break;
5219 case rm_nothing:
5220 break;
5222 default:
5223 gcc_unreachable ();
5226 break;
5228 case rm_unit:
5229 store_alt_unit_usage (regexp, seq, 0, i);
5230 break;
5232 case rm_nothing:
5233 break;
5235 default:
5236 gcc_unreachable ();
5239 /* Check distribution: */
5240 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5241 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5242 unit_usage_ptr != NULL;
5243 unit_usage_ptr = unit_usage_ptr->next)
5244 unit_usage_ptr->unit_decl->last_distribution_check_cycle = -1;
5245 n_alts = REGEXP_ONEOF (regexp)->regexps_num;
5246 marked = VEC_alloc (int, heap, n_alts);
5247 for (i = 0; i < n_alts; i++)
5248 VEC_safe_push (int, heap, marked, 0);
5249 annotation_reservation_message_reported_p = false;
5250 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5252 cycle = i / n_alts;
5253 start = cycle * n_alts;
5254 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5255 unit_usage_ptr != NULL;
5256 unit_usage_ptr = unit_usage_ptr->next)
5258 if (unit_usage_ptr->unit_decl->last_distribution_check_cycle == cycle)
5259 continue;
5260 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5261 for (alt = 0; alt < n_alts; alt++)
5262 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5263 cycle_alt_unit_usages,
5264 start + alt),
5265 unit_usage_ptr->unit_decl))
5266 break;
5267 if (alt >= n_alts)
5268 continue;
5269 memset (VEC_address (int, marked), 0, n_alts * sizeof (int));
5270 for (alt = 0; alt < n_alts; alt++)
5272 if (! unit_present_on_list_p (VEC_index (unit_usage_t,
5273 cycle_alt_unit_usages,
5274 start + alt),
5275 unit_usage_ptr->unit_decl))
5276 continue;
5277 for (j = 0;
5278 j < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages);
5279 j++)
5281 alt2 = j % n_alts;
5282 if (! unit_present_on_list_p
5283 (VEC_index (unit_usage_t, cycle_alt_unit_usages,
5284 start + alt2),
5285 unit_usage_ptr->unit_decl)
5286 && equal_alternatives_p (alt, alt2, n_alts,
5287 unit_usage_ptr
5288 ->unit_decl->automaton_decl))
5290 VEC_replace (int, marked, alt, 1);
5291 VEC_replace (int, marked, alt2, 1);
5295 for (alt = 0; alt < n_alts && VEC_index (int, marked, alt); alt++)
5297 if (alt < n_alts && 0)
5299 if (! annotation_message_reported_p)
5301 fprintf (stderr, "\n");
5302 error ("The following units do not satisfy units-automata distribution rule");
5303 error ("(Unit presence on one alt and its absence on other alt\n");
5304 error (" result in different other automata reservations)");
5305 annotation_message_reported_p = TRUE;
5307 if (! annotation_reservation_message_reported_p)
5309 error ("Reserv %s:", insn_reserv_name);
5310 annotation_reservation_message_reported_p = true;
5312 error (" Unit %s, cycle %d, alt %d, another alt %d",
5313 unit_usage_ptr->unit_decl->name, cycle, i % n_alts, alt);
5317 VEC_free (int, heap, marked);
5318 VEC_free (unit_usage_t, heap, cycle_alt_unit_usages);
5319 obstack_free (&unit_usages, NULL);
5322 /* The function finds units which violates units to automata
5323 distribution rule. If the units exist, report about them. */
5324 static void
5325 check_unit_distributions_to_automata (void)
5327 decl_t decl;
5328 int i;
5330 if (progress_flag)
5331 fprintf (stderr, "Check unit distributions to automata...");
5332 automaton_decls = NULL;
5333 for (i = 0; i < description->decls_num; i++)
5335 decl = description->decls [i];
5336 if (decl->mode == dm_automaton)
5337 VEC_safe_push (decl_t, heap, automaton_decls, decl);
5339 if (VEC_length (decl_t, automaton_decls) > 1)
5341 annotation_message_reported_p = FALSE;
5342 for (i = 0; i < description->decls_num; i++)
5344 decl = description->decls [i];
5345 if (decl->mode == dm_insn_reserv)
5346 check_regexp_units_distribution
5347 (DECL_INSN_RESERV (decl)->name,
5348 DECL_INSN_RESERV (decl)->transformed_regexp);
5351 VEC_free (decl_t, heap, automaton_decls);
5352 if (progress_flag)
5353 fprintf (stderr, "done\n");
5358 /* The page contains code for building alt_states (see comments for
5359 IR) describing all possible insns reservations of an automaton. */
5361 /* Current state being formed for which the current alt_state
5362 refers. */
5363 static state_t state_being_formed;
5365 /* Current alt_state being formed. */
5366 static alt_state_t alt_state_being_formed;
5368 /* This recursive function processes `,' and units in reservation
5369 REGEXP for forming alt_states of AUTOMATON. It is believed that
5370 CURR_CYCLE is start cycle of all reservation REGEXP. */
5371 static int
5372 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5373 int curr_cycle)
5375 int i;
5377 if (regexp == NULL)
5378 return curr_cycle;
5380 switch (regexp->mode)
5382 case rm_unit:
5383 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5384 == automaton->automaton_order_num)
5385 set_state_reserv (state_being_formed, curr_cycle,
5386 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5387 return curr_cycle;
5389 case rm_sequence:
5390 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5391 curr_cycle
5392 = process_seq_for_forming_states
5393 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5394 return curr_cycle;
5396 case rm_allof:
5398 int finish_cycle = 0;
5399 int cycle;
5401 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5403 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5404 ->regexps [i],
5405 automaton, curr_cycle);
5406 if (finish_cycle < cycle)
5407 finish_cycle = cycle;
5409 return finish_cycle;
5412 case rm_nothing:
5413 return curr_cycle;
5415 default:
5416 gcc_unreachable ();
5420 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5421 inserts alt_state into the table. */
5422 static void
5423 finish_forming_alt_state (alt_state_t alt_state,
5424 automaton_t automaton ATTRIBUTE_UNUSED)
5426 state_t state_in_table;
5427 state_t corresponding_state;
5429 corresponding_state = alt_state->state;
5430 state_in_table = insert_state (corresponding_state);
5431 if (state_in_table != corresponding_state)
5433 free_state (corresponding_state);
5434 alt_state->state = state_in_table;
5438 /* The following variable value is current automaton insn for whose
5439 reservation the alt states are created. */
5440 static ainsn_t curr_ainsn;
5442 /* This recursive function processes `|' in reservation REGEXP for
5443 forming alt_states of AUTOMATON. List of the alt states should
5444 have the same order as in the description. */
5445 static void
5446 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5447 int inside_oneof_p)
5449 int i;
5451 if (regexp->mode != rm_oneof)
5453 alt_state_being_formed = get_free_alt_state ();
5454 state_being_formed = get_free_state (1, automaton);
5455 alt_state_being_formed->state = state_being_formed;
5456 /* We inserts in reverse order but we process alternatives also
5457 in reverse order. So we have the same order of alternative
5458 as in the description. */
5459 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5460 curr_ainsn->alt_states = alt_state_being_formed;
5461 (void) process_seq_for_forming_states (regexp, automaton, 0);
5462 finish_forming_alt_state (alt_state_being_formed, automaton);
5464 else
5466 gcc_assert (!inside_oneof_p);
5467 /* We processes it in reverse order to get list with the same
5468 order as in the description. See also the previous
5469 commentary. */
5470 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5471 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5472 automaton, 1);
5476 /* Create nodes alt_state for all AUTOMATON insns. */
5477 static void
5478 create_alt_states (automaton_t automaton)
5480 struct insn_reserv_decl *reserv_decl;
5482 for (curr_ainsn = automaton->ainsn_list;
5483 curr_ainsn != NULL;
5484 curr_ainsn = curr_ainsn->next_ainsn)
5486 reserv_decl = curr_ainsn->insn_reserv_decl;
5487 if (!special_decl_p (reserv_decl))
5489 curr_ainsn->alt_states = NULL;
5490 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5491 automaton, 0);
5492 curr_ainsn->sorted_alt_states
5493 = uniq_sort_alt_states (curr_ainsn->alt_states);
5500 /* The page contains major code for building DFA(s) for fast pipeline
5501 hazards recognition. */
5503 /* The function forms list of ainsns of AUTOMATON with the same
5504 reservation. */
5506 static void
5507 form_ainsn_with_same_reservs (automaton_t automaton)
5509 ainsn_t curr_ainsn;
5510 size_t i;
5511 VEC(ainsn_t, heap) *last_insns = VEC_alloc (ainsn_t, heap, 150);
5513 for (curr_ainsn = automaton->ainsn_list;
5514 curr_ainsn != NULL;
5515 curr_ainsn = curr_ainsn->next_ainsn)
5516 if (special_decl_p (curr_ainsn->insn_reserv_decl))
5518 curr_ainsn->next_same_reservs_insn = NULL;
5519 curr_ainsn->first_insn_with_same_reservs = 1;
5521 else
5523 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5524 if (alt_states_eq
5525 (curr_ainsn->sorted_alt_states,
5526 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5527 break;
5528 curr_ainsn->next_same_reservs_insn = NULL;
5529 if (i < VEC_length (ainsn_t, last_insns))
5531 curr_ainsn->first_insn_with_same_reservs = 0;
5532 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5533 = curr_ainsn;
5534 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5536 else
5538 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5539 curr_ainsn->first_insn_with_same_reservs = 1;
5542 VEC_free (ainsn_t, heap, last_insns);
5545 /* Forming unit reservations which can affect creating the automaton
5546 states achieved from a given state. It permits to build smaller
5547 automata in many cases. We would have the same automata after
5548 the minimization without such optimization, but the automaton
5549 right after the building could be huge. So in other words, usage
5550 of reservs_matter means some minimization during building the
5551 automaton. */
5552 static reserv_sets_t
5553 form_reservs_matter (automaton_t automaton)
5555 int cycle, unit;
5556 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5558 for (cycle = 0; cycle < max_cycles_num; cycle++)
5559 for (unit = 0; unit < description->units_num; unit++)
5560 if (units_array [unit]->automaton_decl
5561 == automaton->corresponding_automaton_decl
5562 && (cycle >= units_array [unit]->min_occ_cycle_num
5563 /* We can not remove queried unit from reservations. */
5564 || units_array [unit]->query_p
5565 /* We can not remove units which are used
5566 `exclusion_set', `presence_set',
5567 `final_presence_set', `absence_set', and
5568 `final_absence_set'. */
5569 || units_array [unit]->in_set_p))
5570 set_unit_reserv (reservs_matter, cycle, unit);
5571 return reservs_matter;
5574 /* The following function creates all states of nondeterministic AUTOMATON. */
5575 static void
5576 make_automaton (automaton_t automaton)
5578 ainsn_t ainsn;
5579 struct insn_reserv_decl *insn_reserv_decl;
5580 alt_state_t alt_state;
5581 state_t state;
5582 state_t start_state;
5583 state_t state2;
5584 VEC(state_t, heap) *state_stack = VEC_alloc(state_t, heap, 150);
5585 int states_n;
5586 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5588 /* Create the start state (empty state). */
5589 start_state = insert_state (get_free_state (1, automaton));
5590 automaton->start_state = start_state;
5591 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5592 VEC_safe_push (state_t, heap, state_stack, start_state);
5593 states_n = 1;
5594 while (VEC_length (state_t, state_stack) != 0)
5596 state = VEC_pop (state_t, state_stack);
5597 for (ainsn = automaton->ainsn_list;
5598 ainsn != NULL;
5599 ainsn = ainsn->next_ainsn)
5600 if (ainsn->first_insn_with_same_reservs)
5602 insn_reserv_decl = ainsn->insn_reserv_decl;
5603 if (!special_decl_p (insn_reserv_decl))
5605 /* We process alt_states in the same order as they are
5606 present in the description. */
5607 for (alt_state = ainsn->alt_states;
5608 alt_state != NULL;
5609 alt_state = alt_state->next_alt_state)
5611 state2 = alt_state->state;
5612 if (!intersected_state_reservs_p (state, state2))
5614 state2 = states_union (state, state2, reservs_matter);
5615 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5617 state2->it_was_placed_in_stack_for_NDFA_forming
5618 = 1;
5619 VEC_safe_push (state_t, heap, state_stack, state2);
5620 states_n++;
5621 if (progress_flag && states_n % 100 == 0)
5622 fprintf (stderr, ".");
5624 add_arc (state, state2, ainsn);
5625 if (!ndfa_flag)
5626 break;
5631 /* Add transition to advance cycle. */
5632 state2 = state_shift (state, reservs_matter);
5633 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5635 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5636 VEC_safe_push (state_t, heap, state_stack, state2);
5637 states_n++;
5638 if (progress_flag && states_n % 100 == 0)
5639 fprintf (stderr, ".");
5641 add_arc (state, state2, automaton->advance_ainsn);
5643 VEC_free (state_t, heap, state_stack);
5646 /* Form lists of all arcs of STATE marked by the same ainsn. */
5647 static void
5648 form_arcs_marked_by_insn (state_t state)
5650 decl_t decl;
5651 arc_t arc;
5652 int i;
5654 for (i = 0; i < description->decls_num; i++)
5656 decl = description->decls [i];
5657 if (decl->mode == dm_insn_reserv)
5658 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5660 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5662 gcc_assert (arc->insn);
5663 arc->next_arc_marked_by_insn
5664 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5665 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5669 /* The function creates composed state (see comments for IR) from
5670 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5671 same insn. If the composed state is not in STATE_STACK yet, it is
5672 pushed into STATE_STACK. */
5674 static int
5675 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5676 VEC(state_t, heap) **state_stack)
5678 state_t state;
5679 alt_state_t alt_state, curr_alt_state;
5680 alt_state_t new_alt_state;
5681 arc_t curr_arc;
5682 arc_t next_arc;
5683 state_t state_in_table;
5684 state_t temp_state;
5685 alt_state_t canonical_alt_states_list;
5686 int alts_number;
5687 int new_state_p = 0;
5689 if (arcs_marked_by_insn == NULL)
5690 return new_state_p;
5691 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5692 state = arcs_marked_by_insn->to_state;
5693 else
5695 gcc_assert (ndfa_flag);
5696 /* Create composed state. */
5697 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5698 curr_alt_state = NULL;
5699 for (curr_arc = arcs_marked_by_insn;
5700 curr_arc != NULL;
5701 curr_arc = curr_arc->next_arc_marked_by_insn)
5702 if (curr_arc->to_state->component_states == NULL)
5704 new_alt_state = get_free_alt_state ();
5705 new_alt_state->next_alt_state = curr_alt_state;
5706 new_alt_state->state = curr_arc->to_state;
5707 curr_alt_state = new_alt_state;
5709 else
5710 for (alt_state = curr_arc->to_state->component_states;
5711 alt_state != NULL;
5712 alt_state = alt_state->next_sorted_alt_state)
5714 new_alt_state = get_free_alt_state ();
5715 new_alt_state->next_alt_state = curr_alt_state;
5716 new_alt_state->state = alt_state->state;
5717 gcc_assert (!alt_state->state->component_states);
5718 curr_alt_state = new_alt_state;
5720 /* There are not identical sets in the alt state list. */
5721 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5722 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5724 temp_state = state;
5725 state = canonical_alt_states_list->state;
5726 free_state (temp_state);
5728 else
5730 state->component_states = canonical_alt_states_list;
5731 state_in_table = insert_state (state);
5732 if (state_in_table != state)
5734 gcc_assert
5735 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5736 free_state (state);
5737 state = state_in_table;
5739 else
5741 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5742 new_state_p = 1;
5743 for (curr_alt_state = state->component_states;
5744 curr_alt_state != NULL;
5745 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5746 for (curr_arc = first_out_arc (curr_alt_state->state);
5747 curr_arc != NULL;
5748 curr_arc = next_out_arc (curr_arc))
5749 if (!collapse_flag
5750 /* When producing collapse-NDFA transitions, we
5751 only add advance-cycle transitions to the
5752 collapsed states. */
5753 || (curr_arc->insn->insn_reserv_decl
5754 != DECL_INSN_RESERV (advance_cycle_insn_decl)))
5755 add_arc (state, curr_arc->to_state, curr_arc->insn);
5757 arcs_marked_by_insn->to_state = state;
5758 for (alts_number = 0,
5759 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5760 curr_arc != NULL;
5761 curr_arc = next_arc)
5763 next_arc = curr_arc->next_arc_marked_by_insn;
5764 remove_arc (original_state, curr_arc);
5765 alts_number++;
5769 if (!state->it_was_placed_in_stack_for_DFA_forming)
5771 state->it_was_placed_in_stack_for_DFA_forming = 1;
5772 VEC_safe_push (state_t, heap, *state_stack, state);
5774 return new_state_p;
5777 /* The function transforms nondeterministic AUTOMATON into
5778 deterministic. */
5780 static void
5781 NDFA_to_DFA (automaton_t automaton)
5783 state_t start_state;
5784 state_t state;
5785 decl_t decl;
5786 VEC(state_t, heap) *state_stack;
5787 int i;
5788 int states_n;
5790 state_stack = VEC_alloc (state_t, heap, 0);
5792 /* Create the start state (empty state). */
5793 start_state = automaton->start_state;
5794 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5795 VEC_safe_push (state_t, heap, state_stack, start_state);
5796 states_n = 1;
5797 while (VEC_length (state_t, state_stack) != 0)
5799 state = VEC_pop (state_t, state_stack);
5800 form_arcs_marked_by_insn (state);
5801 for (i = 0; i < description->decls_num; i++)
5803 decl = description->decls [i];
5804 if (decl->mode == dm_insn_reserv
5805 && decl != collapse_ndfa_insn_decl
5806 && create_composed_state
5807 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5808 &state_stack))
5810 states_n++;
5811 if (progress_flag && states_n % 100 == 0)
5812 fprintf (stderr, ".");
5815 /* Add a transition to collapse the NDFA. */
5816 if (collapse_flag)
5818 if (state->component_states != NULL)
5820 state_t state2 = state->component_states->state;
5821 if (!state2->it_was_placed_in_stack_for_DFA_forming)
5823 state2->it_was_placed_in_stack_for_DFA_forming = 1;
5824 VEC_safe_push (state_t, heap, state_stack, state2);
5826 add_arc (state, state2, automaton->collapse_ainsn);
5828 else
5829 add_arc (state, state, automaton->collapse_ainsn);
5832 VEC_free (state_t, heap, state_stack);
5835 /* The following variable value is current number (1, 2, ...) of passing
5836 graph of states. */
5837 static int curr_state_graph_pass_num;
5839 /* This recursive function passes all states achieved from START_STATE
5840 and applies APPLIED_FUNC to them. */
5841 static void
5842 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5844 arc_t arc;
5846 if (start_state->pass_num == curr_state_graph_pass_num)
5847 return;
5848 start_state->pass_num = curr_state_graph_pass_num;
5849 (*applied_func) (start_state);
5850 for (arc = first_out_arc (start_state);
5851 arc != NULL;
5852 arc = next_out_arc (arc))
5853 pass_state_graph (arc->to_state, applied_func);
5856 /* This recursive function passes all states of AUTOMATON and applies
5857 APPLIED_FUNC to them. */
5858 static void
5859 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5861 curr_state_graph_pass_num++;
5862 pass_state_graph (automaton->start_state, applied_func);
5865 /* The function initializes code for passing of all states. */
5866 static void
5867 initiate_pass_states (void)
5869 curr_state_graph_pass_num = 0;
5872 /* The following vla is used for storing pointers to all achieved
5873 states. */
5874 static VEC(state_t, heap) *all_achieved_states;
5876 /* This function is called by function pass_states to add an achieved
5877 STATE. */
5878 static void
5879 add_achieved_state (state_t state)
5881 VEC_safe_push (state_t, heap, all_achieved_states, state);
5884 /* The function sets up equivalence numbers of insns which mark all
5885 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5886 nonzero value) or by equiv_class_num_2 of the destination state. */
5887 static void
5888 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5890 arc_t arc;
5892 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5894 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5895 arc->insn->insn_reserv_decl->equiv_class_num
5896 = (odd_iteration_flag
5897 ? arc->to_state->equiv_class_num_1
5898 : arc->to_state->equiv_class_num_2);
5899 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5903 /* The function clears equivalence numbers and alt_states in all insns
5904 which mark all out arcs of STATE. */
5905 static void
5906 clear_arc_insns_equiv_num (state_t state)
5908 arc_t arc;
5910 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5911 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5915 /* The following function returns TRUE if STATE reserves the unit with
5916 UNIT_NUM on the first cycle. */
5917 static int
5918 first_cycle_unit_presence (state_t state, int unit_num)
5920 alt_state_t alt_state;
5922 if (state->component_states == NULL)
5923 return test_unit_reserv (state->reservs, 0, unit_num);
5924 else
5926 for (alt_state = state->component_states;
5927 alt_state != NULL;
5928 alt_state = alt_state->next_sorted_alt_state)
5929 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5930 return true;
5932 return false;
5935 /* This fills in the presence_signature[] member of STATE. */
5936 static void
5937 cache_presence (state_t state)
5939 int i, num = 0;
5940 unsigned int sz;
5941 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5942 / (sizeof (int) * CHAR_BIT);
5944 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5945 for (i = 0; i < description->units_num; i++)
5946 if (units_array [i]->query_p)
5948 int presence1_p = first_cycle_unit_presence (state, i);
5949 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5950 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5951 num++;
5955 /* The function returns nonzero value if STATE is not equivalent to
5956 ANOTHER_STATE from the same current partition on equivalence
5957 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5958 output arcs. Iteration of making equivalence partition is defined
5959 by ODD_ITERATION_FLAG. */
5960 static int
5961 state_is_differed (state_t state, state_t another_state,
5962 int odd_iteration_flag)
5964 arc_t arc;
5965 unsigned int sz, si;
5967 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5969 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5970 / (sizeof (int) * CHAR_BIT);
5972 for (si = 0; si < sz; si++)
5973 gcc_assert (state->presence_signature[si]
5974 == another_state->presence_signature[si]);
5976 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5978 if ((odd_iteration_flag
5979 ? arc->to_state->equiv_class_num_1
5980 : arc->to_state->equiv_class_num_2)
5981 != arc->insn->insn_reserv_decl->equiv_class_num)
5982 return 1;
5985 return 0;
5988 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5989 and return -1, 0 or 1. This function can be used as predicate for
5990 qsort(). It requires the member presence_signature[] of both
5991 states be filled. */
5992 static int
5993 compare_states_for_equiv (const void *state_ptr_1,
5994 const void *state_ptr_2)
5996 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5997 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5998 unsigned int sz, si;
5999 if (s1->num_out_arcs < s2->num_out_arcs)
6000 return -1;
6001 else if (s1->num_out_arcs > s2->num_out_arcs)
6002 return 1;
6004 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
6005 / (sizeof (int) * CHAR_BIT);
6007 for (si = 0; si < sz; si++)
6008 if (s1->presence_signature[si] < s2->presence_signature[si])
6009 return -1;
6010 else if (s1->presence_signature[si] > s2->presence_signature[si])
6011 return 1;
6012 return 0;
6015 /* The function makes initial partition of STATES on equivalent
6016 classes and saves it into *CLASSES. This function requires the input
6017 to be sorted via compare_states_for_equiv(). */
6018 static int
6019 init_equiv_class (VEC(state_t, heap) *states, VEC (state_t, heap) **classes)
6021 size_t i;
6022 state_t prev = 0;
6023 int class_num = 1;
6025 *classes = VEC_alloc (state_t, heap, 150);
6026 for (i = 0; i < VEC_length (state_t, states); i++)
6028 state_t state = VEC_index (state_t, states, i);
6029 if (prev)
6031 if (compare_states_for_equiv (&prev, &state) != 0)
6033 VEC_safe_push (state_t, heap, *classes, prev);
6034 class_num++;
6035 prev = NULL;
6038 state->equiv_class_num_1 = class_num;
6039 state->next_equiv_class_state = prev;
6040 prev = state;
6042 if (prev)
6043 VEC_safe_push (state_t, heap, *classes, prev);
6044 return class_num;
6047 /* The function copies pointers to equivalent states from vla FROM
6048 into vla TO. */
6049 static void
6050 copy_equiv_class (VEC(state_t, heap) **to, VEC(state_t, heap) *from)
6052 VEC_free (state_t, heap, *to);
6053 *to = VEC_copy (state_t, heap, from);
6056 /* The function processes equivalence class given by its first state,
6057 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
6058 are not equivalent states, the function partitions the class
6059 removing nonequivalent states and placing them in
6060 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
6061 assigns it to the state equivalence number. If the class has been
6062 partitioned, the function returns nonzero value. */
6063 static int
6064 partition_equiv_class (state_t first_state, int odd_iteration_flag,
6065 VEC(state_t, heap) **next_iteration_classes,
6066 int *new_equiv_class_num_ptr)
6068 state_t new_equiv_class;
6069 int partition_p;
6070 state_t curr_state;
6071 state_t prev_state;
6072 state_t next_state;
6074 partition_p = 0;
6076 while (first_state != NULL)
6078 new_equiv_class = NULL;
6079 if (first_state->next_equiv_class_state != NULL)
6081 /* There are more one states in the class equivalence. */
6082 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
6083 for (prev_state = first_state,
6084 curr_state = first_state->next_equiv_class_state;
6085 curr_state != NULL;
6086 curr_state = next_state)
6088 next_state = curr_state->next_equiv_class_state;
6089 if (state_is_differed (curr_state, first_state,
6090 odd_iteration_flag))
6092 /* Remove curr state from the class equivalence. */
6093 prev_state->next_equiv_class_state = next_state;
6094 /* Add curr state to the new class equivalence. */
6095 curr_state->next_equiv_class_state = new_equiv_class;
6096 if (new_equiv_class == NULL)
6097 (*new_equiv_class_num_ptr)++;
6098 if (odd_iteration_flag)
6099 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
6100 else
6101 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
6102 new_equiv_class = curr_state;
6103 partition_p = 1;
6105 else
6106 prev_state = curr_state;
6108 clear_arc_insns_equiv_num (first_state);
6110 if (new_equiv_class != NULL)
6111 VEC_safe_push (state_t, heap, *next_iteration_classes, new_equiv_class);
6112 first_state = new_equiv_class;
6114 return partition_p;
6117 /* The function finds equivalent states of AUTOMATON. */
6118 static void
6119 evaluate_equiv_classes (automaton_t automaton,
6120 VEC(state_t, heap) **equiv_classes)
6122 int new_equiv_class_num;
6123 int odd_iteration_flag;
6124 int finish_flag;
6125 VEC (state_t, heap) *next_iteration_classes;
6126 size_t i;
6128 all_achieved_states = VEC_alloc (state_t, heap, 1500);
6129 pass_states (automaton, add_achieved_state);
6130 pass_states (automaton, cache_presence);
6131 VEC_qsort (state_t, all_achieved_states, compare_states_for_equiv);
6133 odd_iteration_flag = 0;
6134 new_equiv_class_num = init_equiv_class (all_achieved_states,
6135 &next_iteration_classes);
6139 odd_iteration_flag = !odd_iteration_flag;
6140 finish_flag = 1;
6141 copy_equiv_class (equiv_classes, next_iteration_classes);
6143 /* Transfer equiv numbers for the next iteration. */
6144 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
6145 if (odd_iteration_flag)
6146 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
6147 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
6148 else
6149 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
6150 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
6152 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
6153 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
6154 odd_iteration_flag,
6155 &next_iteration_classes,
6156 &new_equiv_class_num))
6157 finish_flag = 0;
6159 while (!finish_flag);
6160 VEC_free (state_t, heap, next_iteration_classes);
6161 VEC_free (state_t, heap, all_achieved_states);
6164 /* The function merges equivalent states of AUTOMATON. */
6165 static void
6166 merge_states (automaton_t automaton, VEC(state_t, heap) *equiv_classes)
6168 state_t curr_state;
6169 state_t new_state;
6170 state_t first_class_state;
6171 alt_state_t alt_states;
6172 alt_state_t alt_state, new_alt_state;
6173 arc_t curr_arc;
6174 arc_t next_arc;
6175 size_t i;
6177 /* Create states corresponding to equivalence classes containing two
6178 or more states. */
6179 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6181 curr_state = VEC_index (state_t, equiv_classes, i);
6182 if (curr_state->next_equiv_class_state != NULL)
6184 /* There are more one states in the class equivalence. */
6185 /* Create new compound state. */
6186 new_state = get_free_state (0, automaton);
6187 alt_states = NULL;
6188 first_class_state = curr_state;
6189 for (curr_state = first_class_state;
6190 curr_state != NULL;
6191 curr_state = curr_state->next_equiv_class_state)
6193 curr_state->equiv_class_state = new_state;
6194 if (curr_state->component_states == NULL)
6196 new_alt_state = get_free_alt_state ();
6197 new_alt_state->state = curr_state;
6198 new_alt_state->next_alt_state = alt_states;
6199 alt_states = new_alt_state;
6201 else
6202 for (alt_state = curr_state->component_states;
6203 alt_state != NULL;
6204 alt_state = alt_state->next_sorted_alt_state)
6206 new_alt_state = get_free_alt_state ();
6207 new_alt_state->state = alt_state->state;
6208 new_alt_state->next_alt_state = alt_states;
6209 alt_states = new_alt_state;
6212 /* Its is important that alt states were sorted before and
6213 after merging to have the same querying results. */
6214 new_state->component_states = uniq_sort_alt_states (alt_states);
6216 else
6217 curr_state->equiv_class_state = curr_state;
6220 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
6222 curr_state = VEC_index (state_t, equiv_classes, i);
6223 if (curr_state->next_equiv_class_state != NULL)
6225 first_class_state = curr_state;
6226 /* Create new arcs output from the state corresponding to
6227 equiv class. */
6228 for (curr_arc = first_out_arc (first_class_state);
6229 curr_arc != NULL;
6230 curr_arc = next_out_arc (curr_arc))
6231 add_arc (first_class_state->equiv_class_state,
6232 curr_arc->to_state->equiv_class_state,
6233 curr_arc->insn);
6234 /* Delete output arcs from states of given class equivalence. */
6235 for (curr_state = first_class_state;
6236 curr_state != NULL;
6237 curr_state = curr_state->next_equiv_class_state)
6239 if (automaton->start_state == curr_state)
6240 automaton->start_state = curr_state->equiv_class_state;
6241 /* Delete the state and its output arcs. */
6242 for (curr_arc = first_out_arc (curr_state);
6243 curr_arc != NULL;
6244 curr_arc = next_arc)
6246 next_arc = next_out_arc (curr_arc);
6247 free_arc (curr_arc);
6251 else
6253 /* Change `to_state' of arcs output from the state of given
6254 equivalence class. */
6255 for (curr_arc = first_out_arc (curr_state);
6256 curr_arc != NULL;
6257 curr_arc = next_out_arc (curr_arc))
6258 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
6263 /* The function sets up new_cycle_p for states if there is arc to the
6264 state marked by advance_cycle_insn_decl. */
6265 static void
6266 set_new_cycle_flags (state_t state)
6268 arc_t arc;
6270 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6271 if (arc->insn->insn_reserv_decl
6272 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6273 arc->to_state->new_cycle_p = 1;
6276 /* The top level function for minimization of deterministic
6277 AUTOMATON. */
6278 static void
6279 minimize_DFA (automaton_t automaton)
6281 VEC(state_t, heap) *equiv_classes = 0;
6283 evaluate_equiv_classes (automaton, &equiv_classes);
6284 merge_states (automaton, equiv_classes);
6285 pass_states (automaton, set_new_cycle_flags);
6287 VEC_free (state_t, heap, equiv_classes);
6290 /* Values of two variables are counted number of states and arcs in an
6291 automaton. */
6292 static int curr_counted_states_num;
6293 static int curr_counted_arcs_num;
6295 /* The function is called by function `pass_states' to count states
6296 and arcs of an automaton. */
6297 static void
6298 incr_states_and_arcs_nums (state_t state)
6300 arc_t arc;
6302 curr_counted_states_num++;
6303 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6304 curr_counted_arcs_num++;
6307 /* The function counts states and arcs of AUTOMATON. */
6308 static void
6309 count_states_and_arcs (automaton_t automaton, int *states_num,
6310 int *arcs_num)
6312 curr_counted_states_num = 0;
6313 curr_counted_arcs_num = 0;
6314 pass_states (automaton, incr_states_and_arcs_nums);
6315 *states_num = curr_counted_states_num;
6316 *arcs_num = curr_counted_arcs_num;
6319 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6320 recognition after checking and simplifying IR of the
6321 description. */
6322 static void
6323 build_automaton (automaton_t automaton)
6325 int states_num;
6326 int arcs_num;
6328 ticker_on (&NDFA_time);
6329 if (progress_flag)
6331 if (automaton->corresponding_automaton_decl == NULL)
6332 fprintf (stderr, "Create anonymous automaton");
6333 else
6334 fprintf (stderr, "Create automaton `%s'",
6335 automaton->corresponding_automaton_decl->name);
6336 fprintf (stderr, " (1 dot is 100 new states):");
6338 make_automaton (automaton);
6339 if (progress_flag)
6340 fprintf (stderr, " done\n");
6341 ticker_off (&NDFA_time);
6342 count_states_and_arcs (automaton, &states_num, &arcs_num);
6343 automaton->NDFA_states_num = states_num;
6344 automaton->NDFA_arcs_num = arcs_num;
6345 ticker_on (&NDFA_to_DFA_time);
6346 if (progress_flag)
6348 if (automaton->corresponding_automaton_decl == NULL)
6349 fprintf (stderr, "Make anonymous DFA");
6350 else
6351 fprintf (stderr, "Make DFA `%s'",
6352 automaton->corresponding_automaton_decl->name);
6353 fprintf (stderr, " (1 dot is 100 new states):");
6355 NDFA_to_DFA (automaton);
6356 if (progress_flag)
6357 fprintf (stderr, " done\n");
6358 ticker_off (&NDFA_to_DFA_time);
6359 count_states_and_arcs (automaton, &states_num, &arcs_num);
6360 automaton->DFA_states_num = states_num;
6361 automaton->DFA_arcs_num = arcs_num;
6362 if (!no_minimization_flag)
6364 ticker_on (&minimize_time);
6365 if (progress_flag)
6367 if (automaton->corresponding_automaton_decl == NULL)
6368 fprintf (stderr, "Minimize anonymous DFA...");
6369 else
6370 fprintf (stderr, "Minimize DFA `%s'...",
6371 automaton->corresponding_automaton_decl->name);
6373 minimize_DFA (automaton);
6374 if (progress_flag)
6375 fprintf (stderr, "done\n");
6376 ticker_off (&minimize_time);
6377 count_states_and_arcs (automaton, &states_num, &arcs_num);
6378 automaton->minimal_DFA_states_num = states_num;
6379 automaton->minimal_DFA_arcs_num = arcs_num;
6385 /* The page contains code for enumeration of all states of an automaton. */
6387 /* Variable used for enumeration of all states of an automaton. Its
6388 value is current number of automaton states. */
6389 static int curr_state_order_num;
6391 /* The function is called by function `pass_states' for enumerating
6392 states. */
6393 static void
6394 set_order_state_num (state_t state)
6396 state->order_state_num = curr_state_order_num;
6397 curr_state_order_num++;
6400 /* The function enumerates all states of AUTOMATON. */
6401 static void
6402 enumerate_states (automaton_t automaton)
6404 curr_state_order_num = 0;
6405 pass_states (automaton, set_order_state_num);
6406 automaton->achieved_states_num = curr_state_order_num;
6411 /* The page contains code for finding equivalent automaton insns
6412 (ainsns). */
6414 /* The function inserts AINSN into cyclic list
6415 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6416 static ainsn_t
6417 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6418 ainsn_t cyclic_equiv_class_insn_list)
6420 if (cyclic_equiv_class_insn_list == NULL)
6421 ainsn->next_equiv_class_insn = ainsn;
6422 else
6424 ainsn->next_equiv_class_insn
6425 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6426 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6428 return ainsn;
6431 /* The function deletes equiv_class_insn into cyclic list of
6432 equivalent ainsns. */
6433 static void
6434 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6436 ainsn_t curr_equiv_class_insn;
6437 ainsn_t prev_equiv_class_insn;
6439 prev_equiv_class_insn = equiv_class_insn;
6440 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6441 curr_equiv_class_insn != equiv_class_insn;
6442 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6443 prev_equiv_class_insn = curr_equiv_class_insn;
6444 if (prev_equiv_class_insn != equiv_class_insn)
6445 prev_equiv_class_insn->next_equiv_class_insn
6446 = equiv_class_insn->next_equiv_class_insn;
6449 /* The function processes AINSN of a state in order to find equivalent
6450 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6451 state. */
6452 static void
6453 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6455 ainsn_t next_insn;
6456 ainsn_t curr_insn;
6457 ainsn_t cyclic_insn_list;
6458 arc_t arc;
6460 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6461 curr_insn = ainsn;
6462 /* New class of ainsns which are not equivalent to given ainsn. */
6463 cyclic_insn_list = NULL;
6466 next_insn = curr_insn->next_equiv_class_insn;
6467 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6468 if (arc == NULL
6469 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6470 != arc->to_state))
6472 delete_ainsn_from_equiv_class (curr_insn);
6473 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6474 cyclic_insn_list);
6476 curr_insn = next_insn;
6478 while (curr_insn != ainsn);
6481 /* The function processes STATE in order to find equivalent ainsns. */
6482 static void
6483 process_state_for_insn_equiv_partition (state_t state)
6485 arc_t arc;
6486 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6488 /* Process insns of the arcs. */
6489 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6490 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6491 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6492 process_insn_equiv_class (arc->insn, insn_arcs_array);
6494 free (insn_arcs_array);
6497 /* The function searches for equivalent ainsns of AUTOMATON. */
6498 static void
6499 set_insn_equiv_classes (automaton_t automaton)
6501 ainsn_t ainsn;
6502 ainsn_t first_insn;
6503 ainsn_t curr_insn;
6504 ainsn_t cyclic_insn_list;
6505 ainsn_t insn_with_same_reservs;
6506 int equiv_classes_num;
6508 /* All insns are included in one equivalence class. */
6509 cyclic_insn_list = NULL;
6510 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6511 if (ainsn->first_insn_with_same_reservs)
6512 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6513 cyclic_insn_list);
6514 /* Process insns in order to make equivalence partition. */
6515 pass_states (automaton, process_state_for_insn_equiv_partition);
6516 /* Enumerate equiv classes. */
6517 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6518 /* Set undefined value. */
6519 ainsn->insn_equiv_class_num = -1;
6520 equiv_classes_num = 0;
6521 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6522 if (ainsn->insn_equiv_class_num < 0)
6524 first_insn = ainsn;
6525 gcc_assert (first_insn->first_insn_with_same_reservs);
6526 first_insn->first_ainsn_with_given_equivalence_num = 1;
6527 curr_insn = first_insn;
6530 for (insn_with_same_reservs = curr_insn;
6531 insn_with_same_reservs != NULL;
6532 insn_with_same_reservs
6533 = insn_with_same_reservs->next_same_reservs_insn)
6534 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6535 curr_insn = curr_insn->next_equiv_class_insn;
6537 while (curr_insn != first_insn);
6538 equiv_classes_num++;
6540 automaton->insn_equiv_classes_num = equiv_classes_num;
6545 /* This page contains code for creating DFA(s) and calls functions
6546 building them. */
6549 /* The following value is used to prevent floating point overflow for
6550 estimating an automaton bound. The value should be less DBL_MAX on
6551 the host machine. We use here approximate minimum of maximal
6552 double floating point value required by ANSI C standard. It
6553 will work for non ANSI sun compiler too. */
6555 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6557 /* The function estimate size of the single DFA used by PHR (pipeline
6558 hazards recognizer). */
6559 static double
6560 estimate_one_automaton_bound (void)
6562 decl_t decl;
6563 double one_automaton_estimation_bound;
6564 double root_value;
6565 int i;
6567 one_automaton_estimation_bound = 1.0;
6568 for (i = 0; i < description->decls_num; i++)
6570 decl = description->decls [i];
6571 if (decl->mode == dm_unit)
6573 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6574 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6575 / automata_num);
6576 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6577 > one_automaton_estimation_bound)
6578 one_automaton_estimation_bound *= root_value;
6581 return one_automaton_estimation_bound;
6584 /* The function compares unit declarations according to their maximal
6585 cycle in reservations. */
6586 static int
6587 compare_max_occ_cycle_nums (const void *unit_decl_1,
6588 const void *unit_decl_2)
6590 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6591 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6592 return 1;
6593 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6594 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6595 return 0;
6596 else
6597 return -1;
6600 /* The function makes heuristic assigning automata to units. Actually
6601 efficacy of the algorithm has been checked yet??? */
6603 static void
6604 units_to_automata_heuristic_distr (void)
6606 double estimation_bound;
6607 int automaton_num;
6608 int rest_units_num;
6609 double bound_value;
6610 unit_decl_t *unit_decls;
6611 int i, j;
6613 if (description->units_num == 0)
6614 return;
6615 estimation_bound = estimate_one_automaton_bound ();
6616 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6618 for (i = 0, j = 0; i < description->decls_num; i++)
6619 if (description->decls[i]->mode == dm_unit)
6620 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6621 gcc_assert (j == description->units_num);
6623 qsort (unit_decls, description->units_num,
6624 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6626 automaton_num = 0;
6627 bound_value = unit_decls[0]->max_occ_cycle_num;
6628 unit_decls[0]->corresponding_automaton_num = automaton_num;
6630 for (i = 1; i < description->units_num; i++)
6632 rest_units_num = description->units_num - i + 1;
6633 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6634 if (automaton_num < automata_num - 1
6635 && ((automata_num - automaton_num - 1 == rest_units_num)
6636 || (bound_value
6637 > (estimation_bound
6638 / unit_decls[i]->max_occ_cycle_num))))
6640 bound_value = unit_decls[i]->max_occ_cycle_num;
6641 automaton_num++;
6643 else
6644 bound_value *= unit_decls[i]->max_occ_cycle_num;
6645 unit_decls[i]->corresponding_automaton_num = automaton_num;
6647 gcc_assert (automaton_num == automata_num - 1);
6648 free (unit_decls);
6651 /* The functions creates automaton insns for each automata. Automaton
6652 insn is simply insn for given automaton which makes reservation
6653 only of units of the automaton. */
6654 static void
6655 create_ainsns (automaton_t automaton)
6657 decl_t decl;
6658 ainsn_t first_ainsn;
6659 ainsn_t curr_ainsn;
6660 ainsn_t prev_ainsn;
6661 int i;
6663 first_ainsn = NULL;
6664 prev_ainsn = NULL;
6665 for (i = 0; i < description->decls_num; i++)
6667 decl = description->decls [i];
6668 if (decl->mode == dm_insn_reserv)
6670 curr_ainsn = XCREATENODE (struct ainsn);
6671 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6672 curr_ainsn->important_p = FALSE;
6673 curr_ainsn->next_ainsn = NULL;
6674 if (prev_ainsn == NULL)
6675 first_ainsn = curr_ainsn;
6676 else
6677 prev_ainsn->next_ainsn = curr_ainsn;
6678 if (decl == advance_cycle_insn_decl)
6679 automaton->advance_ainsn = curr_ainsn;
6680 else if (decl == collapse_ndfa_insn_decl)
6681 automaton->collapse_ainsn = curr_ainsn;
6682 prev_ainsn = curr_ainsn;
6685 automaton->ainsn_list = first_ainsn;
6688 /* The function assigns automata to units according to constructions
6689 `define_automaton' in the description. */
6690 static void
6691 units_to_automata_distr (void)
6693 decl_t decl;
6694 int i;
6696 for (i = 0; i < description->decls_num; i++)
6698 decl = description->decls [i];
6699 if (decl->mode == dm_unit)
6701 if (DECL_UNIT (decl)->automaton_decl == NULL
6702 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6703 == NULL))
6704 /* Distribute to the first automaton. */
6705 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6706 else
6707 DECL_UNIT (decl)->corresponding_automaton_num
6708 = (DECL_UNIT (decl)->automaton_decl
6709 ->corresponding_automaton->automaton_order_num);
6714 /* The function creates DFA(s) for fast pipeline hazards recognition
6715 after checking and simplifying IR of the description. */
6716 static void
6717 create_automata (void)
6719 automaton_t curr_automaton;
6720 automaton_t prev_automaton;
6721 decl_t decl;
6722 int curr_automaton_num;
6723 int i;
6725 if (automata_num != 0)
6727 units_to_automata_heuristic_distr ();
6728 for (prev_automaton = NULL, curr_automaton_num = 0;
6729 curr_automaton_num < automata_num;
6730 curr_automaton_num++, prev_automaton = curr_automaton)
6732 curr_automaton = XCREATENODE (struct automaton);
6733 create_ainsns (curr_automaton);
6734 curr_automaton->corresponding_automaton_decl = NULL;
6735 curr_automaton->next_automaton = NULL;
6736 curr_automaton->automaton_order_num = curr_automaton_num;
6737 if (prev_automaton == NULL)
6738 description->first_automaton = curr_automaton;
6739 else
6740 prev_automaton->next_automaton = curr_automaton;
6743 else
6745 curr_automaton_num = 0;
6746 prev_automaton = NULL;
6747 for (i = 0; i < description->decls_num; i++)
6749 decl = description->decls [i];
6750 if (decl->mode == dm_automaton
6751 && DECL_AUTOMATON (decl)->automaton_is_used)
6753 curr_automaton = XCREATENODE (struct automaton);
6754 create_ainsns (curr_automaton);
6755 curr_automaton->corresponding_automaton_decl
6756 = DECL_AUTOMATON (decl);
6757 curr_automaton->next_automaton = NULL;
6758 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6759 curr_automaton->automaton_order_num = curr_automaton_num;
6760 if (prev_automaton == NULL)
6761 description->first_automaton = curr_automaton;
6762 else
6763 prev_automaton->next_automaton = curr_automaton;
6764 curr_automaton_num++;
6765 prev_automaton = curr_automaton;
6768 if (curr_automaton_num == 0)
6770 curr_automaton = XCREATENODE (struct automaton);
6771 create_ainsns (curr_automaton);
6772 curr_automaton->corresponding_automaton_decl = NULL;
6773 curr_automaton->next_automaton = NULL;
6774 description->first_automaton = curr_automaton;
6776 units_to_automata_distr ();
6778 NDFA_time = create_ticker ();
6779 ticker_off (&NDFA_time);
6780 NDFA_to_DFA_time = create_ticker ();
6781 ticker_off (&NDFA_to_DFA_time);
6782 minimize_time = create_ticker ();
6783 ticker_off (&minimize_time);
6784 equiv_time = create_ticker ();
6785 ticker_off (&equiv_time);
6786 for (curr_automaton = description->first_automaton;
6787 curr_automaton != NULL;
6788 curr_automaton = curr_automaton->next_automaton)
6790 if (progress_flag)
6792 if (curr_automaton->corresponding_automaton_decl == NULL)
6793 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6794 else
6795 fprintf (stderr, "Prepare automaton `%s' creation...",
6796 curr_automaton->corresponding_automaton_decl->name);
6798 create_alt_states (curr_automaton);
6799 form_ainsn_with_same_reservs (curr_automaton);
6800 if (progress_flag)
6801 fprintf (stderr, "done\n");
6802 build_automaton (curr_automaton);
6803 enumerate_states (curr_automaton);
6804 ticker_on (&equiv_time);
6805 set_insn_equiv_classes (curr_automaton);
6806 ticker_off (&equiv_time);
6812 /* This page contains code for forming string representation of
6813 regexp. The representation is formed on IR obstack. So you should
6814 not work with IR obstack between regexp_representation and
6815 finish_regexp_representation calls. */
6817 /* This recursive function forms string representation of regexp
6818 (without tailing '\0'). */
6819 static void
6820 form_regexp (regexp_t regexp)
6822 int i;
6824 switch (regexp->mode)
6826 case rm_unit: case rm_reserv:
6828 const char *name = (regexp->mode == rm_unit
6829 ? REGEXP_UNIT (regexp)->name
6830 : REGEXP_RESERV (regexp)->name);
6832 obstack_grow (&irp, name, strlen (name));
6833 break;
6836 case rm_sequence:
6837 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6839 if (i != 0)
6840 obstack_1grow (&irp, ',');
6841 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6843 break;
6845 case rm_allof:
6846 obstack_1grow (&irp, '(');
6847 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6849 if (i != 0)
6850 obstack_1grow (&irp, '+');
6851 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6852 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6853 obstack_1grow (&irp, '(');
6854 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6855 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6856 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6857 obstack_1grow (&irp, ')');
6859 obstack_1grow (&irp, ')');
6860 break;
6862 case rm_oneof:
6863 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6865 if (i != 0)
6866 obstack_1grow (&irp, '|');
6867 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6868 obstack_1grow (&irp, '(');
6869 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6870 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6871 obstack_1grow (&irp, ')');
6873 break;
6875 case rm_repeat:
6877 char digits [30];
6879 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6880 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6881 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6882 obstack_1grow (&irp, '(');
6883 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6884 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6885 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6886 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6887 obstack_1grow (&irp, ')');
6888 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6889 obstack_grow (&irp, digits, strlen (digits));
6890 break;
6893 case rm_nothing:
6894 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6895 break;
6897 default:
6898 gcc_unreachable ();
6902 /* The function returns string representation of REGEXP on IR
6903 obstack. */
6904 static const char *
6905 regexp_representation (regexp_t regexp)
6907 form_regexp (regexp);
6908 obstack_1grow (&irp, '\0');
6909 return obstack_base (&irp);
6912 /* The function frees memory allocated for last formed string
6913 representation of regexp. */
6914 static void
6915 finish_regexp_representation (void)
6917 int length = obstack_object_size (&irp);
6919 obstack_blank_fast (&irp, -length);
6924 /* This page contains code for output PHR (pipeline hazards recognizer). */
6926 /* The function outputs minimal C type which is sufficient for
6927 representation numbers in range min_range_value and
6928 max_range_value. Because host machine and build machine may be
6929 different, we use here minimal values required by ANSI C standard
6930 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6931 approximation. */
6933 static void
6934 output_range_type (FILE *f, long int min_range_value,
6935 long int max_range_value)
6937 if (min_range_value >= 0 && max_range_value <= 255)
6938 fprintf (f, "unsigned char");
6939 else if (min_range_value >= -127 && max_range_value <= 127)
6940 fprintf (f, "signed char");
6941 else if (min_range_value >= 0 && max_range_value <= 65535)
6942 fprintf (f, "unsigned short");
6943 else if (min_range_value >= -32767 && max_range_value <= 32767)
6944 fprintf (f, "short");
6945 else
6946 fprintf (f, "int");
6949 /* The function outputs all initialization values of VECT. */
6950 static void
6951 output_vect (vla_hwint_t vect)
6953 int els_on_line;
6954 size_t vect_length = VEC_length (vect_el_t, vect);
6955 size_t i;
6957 els_on_line = 1;
6958 if (vect_length == 0)
6959 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6960 else
6961 for (i = 0; i < vect_length; i++)
6963 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6964 if (els_on_line == 10)
6966 els_on_line = 0;
6967 fputs (",\n", output_file);
6969 else if (i < vect_length-1)
6970 fputs (", ", output_file);
6971 els_on_line++;
6975 /* The following is name of the structure which represents DFA(s) for
6976 PHR. */
6977 #define CHIP_NAME "DFA_chip"
6979 /* The following is name of member which represents state of a DFA for
6980 PHR. */
6981 static void
6982 output_chip_member_name (FILE *f, automaton_t automaton)
6984 if (automaton->corresponding_automaton_decl == NULL)
6985 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6986 else
6987 fprintf (f, "%s_automaton_state",
6988 automaton->corresponding_automaton_decl->name);
6991 /* The following is name of temporary variable which stores state of a
6992 DFA for PHR. */
6993 static void
6994 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6996 fprintf (f, "_");
6997 output_chip_member_name (f, automaton);
7000 /* This is name of macro value which is code of pseudo_insns
7001 representing advancing cpu cycle and collapsing the NDFA.
7002 Its value is used as internal code unknown insn. */
7003 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
7004 #define COLLAPSE_NDFA_VALUE_NAME "NDFA__COLLAPSE"
7006 /* Output name of translate vector for given automaton. */
7007 static void
7008 output_translate_vect_name (FILE *f, automaton_t automaton)
7010 if (automaton->corresponding_automaton_decl == NULL)
7011 fprintf (f, "translate_%d", automaton->automaton_order_num);
7012 else
7013 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
7016 /* Output name for simple transition table representation. */
7017 static void
7018 output_trans_full_vect_name (FILE *f, automaton_t automaton)
7020 if (automaton->corresponding_automaton_decl == NULL)
7021 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7022 else
7023 fprintf (f, "%s_transitions",
7024 automaton->corresponding_automaton_decl->name);
7027 /* Output name of comb vector of the transition table for given
7028 automaton. */
7029 static void
7030 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
7032 if (automaton->corresponding_automaton_decl == NULL)
7033 fprintf (f, "transitions_%d", automaton->automaton_order_num);
7034 else
7035 fprintf (f, "%s_transitions",
7036 automaton->corresponding_automaton_decl->name);
7039 /* Output name of check vector of the transition table for given
7040 automaton. */
7041 static void
7042 output_trans_check_vect_name (FILE *f, automaton_t automaton)
7044 if (automaton->corresponding_automaton_decl == NULL)
7045 fprintf (f, "check_%d", automaton->automaton_order_num);
7046 else
7047 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
7050 /* Output name of base vector of the transition table for given
7051 automaton. */
7052 static void
7053 output_trans_base_vect_name (FILE *f, automaton_t automaton)
7055 if (automaton->corresponding_automaton_decl == NULL)
7056 fprintf (f, "base_%d", automaton->automaton_order_num);
7057 else
7058 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
7061 /* Output name of simple min issue delay table representation. */
7062 static void
7063 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
7065 if (automaton->corresponding_automaton_decl == NULL)
7066 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
7067 else
7068 fprintf (f, "%s_min_issue_delay",
7069 automaton->corresponding_automaton_decl->name);
7072 /* Output name of deadlock vector for given automaton. */
7073 static void
7074 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
7076 if (automaton->corresponding_automaton_decl == NULL)
7077 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
7078 else
7079 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
7082 /* Output name of reserved units table for AUTOMATON into file F. */
7083 static void
7084 output_reserved_units_table_name (FILE *f, automaton_t automaton)
7086 if (automaton->corresponding_automaton_decl == NULL)
7087 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
7088 else
7089 fprintf (f, "%s_reserved_units",
7090 automaton->corresponding_automaton_decl->name);
7093 /* Name of the PHR interface macro. */
7094 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
7096 /* Names of an internal functions: */
7097 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
7099 /* This is external type of DFA(s) state. */
7100 #define STATE_TYPE_NAME "state_t"
7102 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
7104 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
7106 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
7108 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
7110 /* Name of cache of insn dfa codes. */
7111 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
7113 /* Name of length of cache of insn dfa codes. */
7114 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
7116 /* Names of the PHR interface functions: */
7117 #define SIZE_FUNC_NAME "state_size"
7119 #define TRANSITION_FUNC_NAME "state_transition"
7121 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
7123 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
7125 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
7127 #define RESET_FUNC_NAME "state_reset"
7129 #define INSN_LATENCY_FUNC_NAME "insn_latency"
7131 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
7133 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
7135 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
7137 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
7139 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
7141 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
7143 #define DFA_START_FUNC_NAME "dfa_start"
7145 #define DFA_FINISH_FUNC_NAME "dfa_finish"
7147 /* Names of parameters of the PHR interface functions. */
7148 #define STATE_NAME "state"
7150 #define INSN_PARAMETER_NAME "insn"
7152 #define INSN2_PARAMETER_NAME "insn2"
7154 #define CHIP_PARAMETER_NAME "chip"
7156 #define FILE_PARAMETER_NAME "f"
7158 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
7160 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
7162 /* Names of the variables whose values are internal insn code of rtx
7163 insn. */
7164 #define INTERNAL_INSN_CODE_NAME "insn_code"
7166 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
7168 /* Names of temporary variables in some functions. */
7169 #define TEMPORARY_VARIABLE_NAME "temp"
7171 #define I_VARIABLE_NAME "i"
7173 /* Name of result variable in some functions. */
7174 #define RESULT_VARIABLE_NAME "res"
7176 /* Name of function (attribute) to translate insn into internal insn
7177 code. */
7178 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
7180 /* Name of function (attribute) to translate insn into internal insn
7181 code with caching. */
7182 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
7184 /* Output C type which is used for representation of codes of states
7185 of AUTOMATON. */
7186 static void
7187 output_state_member_type (FILE *f, automaton_t automaton)
7189 output_range_type (f, 0, automaton->achieved_states_num);
7192 /* Output definition of the structure representing current DFA(s)
7193 state(s). */
7194 static void
7195 output_chip_definitions (void)
7197 automaton_t automaton;
7199 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
7200 for (automaton = description->first_automaton;
7201 automaton != NULL;
7202 automaton = automaton->next_automaton)
7204 fprintf (output_file, " ");
7205 output_state_member_type (output_file, automaton);
7206 fprintf (output_file, " ");
7207 output_chip_member_name (output_file, automaton);
7208 fprintf (output_file, ";\n");
7210 fprintf (output_file, "};\n\n");
7211 #if 0
7212 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
7213 #endif
7217 /* The function outputs translate vector of internal insn code into
7218 insn equivalence class number. The equivalence class number is
7219 used to access to table and vectors representing DFA(s). */
7220 static void
7221 output_translate_vect (automaton_t automaton)
7223 ainsn_t ainsn;
7224 int insn_value;
7225 vla_hwint_t translate_vect;
7227 translate_vect = VEC_alloc (vect_el_t, heap, description->insns_num);
7229 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
7230 /* Undefined value */
7231 VEC_quick_push (vect_el_t, translate_vect,
7232 automaton->insn_equiv_classes_num);
7234 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7235 VEC_replace (vect_el_t, translate_vect,
7236 ainsn->insn_reserv_decl->insn_num,
7237 ainsn->insn_equiv_class_num);
7239 fprintf (output_file,
7240 "/* Vector translating external insn codes to internal ones.*/\n");
7241 fprintf (output_file, "static const ");
7242 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
7243 fprintf (output_file, " ");
7244 output_translate_vect_name (output_file, automaton);
7245 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7246 output_vect (translate_vect);
7247 fprintf (output_file, "};\n\n");
7248 VEC_free (vect_el_t, heap, translate_vect);
7251 /* The value in a table state x ainsn -> something which represents
7252 undefined value. */
7253 static int undefined_vect_el_value;
7255 /* The following function returns nonzero value if the best
7256 representation of the table is comb vector. */
7257 static int
7258 comb_vect_p (state_ainsn_table_t tab)
7260 if (no_comb_flag)
7261 return false;
7262 return (2 * VEC_length (vect_el_t, tab->full_vect)
7263 > 5 * VEC_length (vect_el_t, tab->comb_vect));
7266 /* The following function creates new table for AUTOMATON. */
7267 static state_ainsn_table_t
7268 create_state_ainsn_table (automaton_t automaton)
7270 state_ainsn_table_t tab;
7271 int full_vect_length;
7272 int i;
7274 tab = XCREATENODE (struct state_ainsn_table);
7275 tab->automaton = automaton;
7277 tab->comb_vect = VEC_alloc (vect_el_t, heap, 10000);
7278 tab->check_vect = VEC_alloc (vect_el_t, heap, 10000);
7280 tab->base_vect = 0;
7281 VEC_safe_grow (vect_el_t, heap, tab->base_vect,
7282 automaton->achieved_states_num);
7284 full_vect_length = (automaton->insn_equiv_classes_num
7285 * automaton->achieved_states_num);
7286 tab->full_vect = VEC_alloc (vect_el_t, heap, full_vect_length);
7287 for (i = 0; i < full_vect_length; i++)
7288 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7290 tab->min_base_vect_el_value = 0;
7291 tab->max_base_vect_el_value = 0;
7292 tab->min_comb_vect_el_value = 0;
7293 tab->max_comb_vect_el_value = 0;
7294 return tab;
7297 /* The following function outputs the best C representation of the
7298 table TAB of given TABLE_NAME. */
7299 static void
7300 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7301 void (*output_full_vect_name_func) (FILE *, automaton_t),
7302 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7303 void (*output_check_vect_name_func) (FILE *, automaton_t),
7304 void (*output_base_vect_name_func) (FILE *, automaton_t))
7306 if (!comb_vect_p (tab))
7308 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7309 fprintf (output_file, "static const ");
7310 output_range_type (output_file, tab->min_comb_vect_el_value,
7311 tab->max_comb_vect_el_value);
7312 fprintf (output_file, " ");
7313 (*output_full_vect_name_func) (output_file, tab->automaton);
7314 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7315 output_vect (tab->full_vect);
7316 fprintf (output_file, "};\n\n");
7318 else
7320 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7321 fprintf (output_file, "static const ");
7322 output_range_type (output_file, tab->min_comb_vect_el_value,
7323 tab->max_comb_vect_el_value);
7324 fprintf (output_file, " ");
7325 (*output_comb_vect_name_func) (output_file, tab->automaton);
7326 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7327 output_vect (tab->comb_vect);
7328 fprintf (output_file, "};\n\n");
7329 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7330 fprintf (output_file, "static const ");
7331 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7332 fprintf (output_file, " ");
7333 (*output_check_vect_name_func) (output_file, tab->automaton);
7334 fprintf (output_file, "[] = {\n");
7335 output_vect (tab->check_vect);
7336 fprintf (output_file, "};\n\n");
7337 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7338 fprintf (output_file, "static const ");
7339 output_range_type (output_file, tab->min_base_vect_el_value,
7340 tab->max_base_vect_el_value);
7341 fprintf (output_file, " ");
7342 (*output_base_vect_name_func) (output_file, tab->automaton);
7343 fprintf (output_file, "[] = {\n");
7344 output_vect (tab->base_vect);
7345 fprintf (output_file, "};\n\n");
7349 /* The following function adds vector VECT to table TAB as its line
7350 with number VECT_NUM. */
7351 static void
7352 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7354 int vect_length;
7355 size_t real_vect_length;
7356 int comb_vect_index;
7357 int comb_vect_els_num;
7358 int vect_index;
7359 int first_unempty_vect_index;
7360 int additional_els_num;
7361 int no_state_value;
7362 vect_el_t vect_el;
7363 int i;
7364 unsigned long vect_mask, comb_vect_mask;
7366 vect_length = VEC_length (vect_el_t, vect);
7367 gcc_assert (vect_length);
7368 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7369 real_vect_length = tab->automaton->insn_equiv_classes_num;
7370 /* Form full vector in the table: */
7372 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7373 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7374 VEC_safe_grow (vect_el_t, heap, tab->full_vect,
7375 full_base + vect_length);
7376 for (i = 0; i < vect_length; i++)
7377 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7378 VEC_index (vect_el_t, vect, i));
7381 /* The comb_vect min/max values are also used for the full vector, so
7382 compute them now. */
7383 for (vect_index = 0; vect_index < vect_length; vect_index++)
7384 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7386 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7387 gcc_assert (x >= 0);
7388 if (tab->max_comb_vect_el_value < x)
7389 tab->max_comb_vect_el_value = x;
7390 if (tab->min_comb_vect_el_value > x)
7391 tab->min_comb_vect_el_value = x;
7393 if (no_comb_flag)
7394 return;
7396 /* Form comb vector in the table: */
7397 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7398 == VEC_length (vect_el_t, tab->check_vect));
7400 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7401 for (first_unempty_vect_index = 0;
7402 first_unempty_vect_index < vect_length;
7403 first_unempty_vect_index++)
7404 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7405 != undefined_vect_el_value)
7406 break;
7408 /* Search for the place in comb vect for the inserted vect. */
7410 /* Slow case. */
7411 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7413 for (comb_vect_index = 0;
7414 comb_vect_index < comb_vect_els_num;
7415 comb_vect_index++)
7417 for (vect_index = first_unempty_vect_index;
7418 vect_index < vect_length
7419 && vect_index + comb_vect_index < comb_vect_els_num;
7420 vect_index++)
7421 if (VEC_index (vect_el_t, vect, vect_index)
7422 != undefined_vect_el_value
7423 && (VEC_index (vect_el_t, tab->comb_vect,
7424 vect_index + comb_vect_index)
7425 != undefined_vect_el_value))
7426 break;
7427 if (vect_index >= vect_length
7428 || vect_index + comb_vect_index >= comb_vect_els_num)
7429 break;
7431 goto found;
7434 /* Fast case. */
7435 vect_mask = 0;
7436 for (vect_index = first_unempty_vect_index;
7437 vect_index < vect_length;
7438 vect_index++)
7440 vect_mask = vect_mask << 1;
7441 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7442 vect_mask |= 1;
7445 /* Search for the place in comb vect for the inserted vect. */
7446 comb_vect_index = 0;
7447 if (comb_vect_els_num == 0)
7448 goto found;
7450 comb_vect_mask = 0;
7451 for (vect_index = first_unempty_vect_index;
7452 vect_index < vect_length && vect_index < comb_vect_els_num;
7453 vect_index++)
7455 comb_vect_mask <<= 1;
7456 if (vect_index + comb_vect_index < comb_vect_els_num
7457 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7458 != undefined_vect_el_value)
7459 comb_vect_mask |= 1;
7461 if ((vect_mask & comb_vect_mask) == 0)
7462 goto found;
7464 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7465 comb_vect_index++, i++)
7467 comb_vect_mask = (comb_vect_mask << 1) | 1;
7468 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7469 == undefined_vect_el_value);
7470 if ((vect_mask & comb_vect_mask) == 0)
7471 goto found;
7473 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7475 comb_vect_mask <<= 1;
7476 if ((vect_mask & comb_vect_mask) == 0)
7477 goto found;
7480 found:
7481 /* Slot was found. */
7482 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7483 if (additional_els_num < 0)
7484 additional_els_num = 0;
7485 /* Expand comb and check vectors. */
7486 vect_el = undefined_vect_el_value;
7487 no_state_value = tab->automaton->achieved_states_num;
7488 while (additional_els_num > 0)
7490 VEC_safe_push (vect_el_t, heap, tab->comb_vect, vect_el);
7491 VEC_safe_push (vect_el_t, heap, tab->check_vect, no_state_value);
7492 additional_els_num--;
7494 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7495 >= comb_vect_index + real_vect_length);
7496 /* Fill comb and check vectors. */
7497 for (vect_index = 0; vect_index < vect_length; vect_index++)
7498 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7500 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7501 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7502 comb_vect_index + vect_index)
7503 == undefined_vect_el_value);
7504 gcc_assert (x >= 0);
7505 VEC_replace (vect_el_t, tab->comb_vect,
7506 comb_vect_index + vect_index, x);
7507 VEC_replace (vect_el_t, tab->check_vect,
7508 comb_vect_index + vect_index, vect_num);
7510 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7511 tab->max_comb_vect_el_value = undefined_vect_el_value;
7512 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7513 tab->min_comb_vect_el_value = undefined_vect_el_value;
7514 if (tab->max_base_vect_el_value < comb_vect_index)
7515 tab->max_base_vect_el_value = comb_vect_index;
7516 if (tab->min_base_vect_el_value > comb_vect_index)
7517 tab->min_base_vect_el_value = comb_vect_index;
7519 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7522 /* Return number of out arcs of STATE. */
7523 static int
7524 out_state_arcs_num (const_state_t state)
7526 int result;
7527 arc_t arc;
7529 result = 0;
7530 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7532 gcc_assert (arc->insn);
7533 if (arc->insn->first_ainsn_with_given_equivalence_num)
7534 result++;
7536 return result;
7539 /* Compare number of possible transitions from the states. */
7540 static int
7541 compare_transition_els_num (const void *state_ptr_1,
7542 const void *state_ptr_2)
7544 const int transition_els_num_1
7545 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7546 const int transition_els_num_2
7547 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7549 if (transition_els_num_1 < transition_els_num_2)
7550 return 1;
7551 else if (transition_els_num_1 == transition_els_num_2)
7552 return 0;
7553 else
7554 return -1;
7557 /* The function adds element EL_VALUE to vector VECT for a table state
7558 x AINSN. */
7559 static void
7560 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7562 int equiv_class_num;
7563 int vect_index;
7565 gcc_assert (ainsn);
7566 equiv_class_num = ainsn->insn_equiv_class_num;
7567 for (vect_index = VEC_length (vect_el_t, *vect);
7568 vect_index <= equiv_class_num;
7569 vect_index++)
7570 VEC_safe_push (vect_el_t, heap, *vect, undefined_vect_el_value);
7571 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7574 /* This is for forming vector of states of an automaton. */
7575 static VEC(state_t, heap) *output_states_vect;
7577 /* The function is called by function pass_states. The function adds
7578 STATE to `output_states_vect'. */
7579 static void
7580 add_states_vect_el (state_t state)
7582 VEC_safe_push (state_t, heap, output_states_vect, state);
7585 /* Form and output vectors (comb, check, base or full vector)
7586 representing transition table of AUTOMATON. */
7587 static void
7588 output_trans_table (automaton_t automaton)
7590 size_t i;
7591 arc_t arc;
7592 vla_hwint_t transition_vect = 0;
7594 undefined_vect_el_value = automaton->achieved_states_num;
7595 automaton->trans_table = create_state_ainsn_table (automaton);
7596 /* Create vect of pointers to states ordered by num of transitions
7597 from the state (state with the maximum num is the first). */
7598 output_states_vect = 0;
7599 pass_states (automaton, add_states_vect_el);
7600 VEC_qsort (state_t, output_states_vect, compare_transition_els_num);
7602 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7604 VEC_truncate (vect_el_t, transition_vect, 0);
7605 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7606 arc != NULL;
7607 arc = next_out_arc (arc))
7609 gcc_assert (arc->insn);
7610 if (arc->insn->first_ainsn_with_given_equivalence_num)
7611 add_vect_el (&transition_vect, arc->insn,
7612 arc->to_state->order_state_num);
7614 add_vect (automaton->trans_table,
7615 VEC_index (state_t, output_states_vect, i)->order_state_num,
7616 transition_vect);
7618 output_state_ainsn_table
7619 (automaton->trans_table, "state transitions",
7620 output_trans_full_vect_name, output_trans_comb_vect_name,
7621 output_trans_check_vect_name, output_trans_base_vect_name);
7623 VEC_free (state_t, heap, output_states_vect);
7624 VEC_free (vect_el_t, heap, transition_vect);
7627 /* Form and output vectors representing minimal issue delay table of
7628 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7629 the ainsn. */
7630 static void
7631 output_min_issue_delay_table (automaton_t automaton)
7633 vla_hwint_t min_issue_delay_vect;
7634 vla_hwint_t compressed_min_issue_delay_vect;
7635 ainsn_t ainsn;
7636 size_t i;
7637 size_t min_issue_delay_len, compressed_min_issue_delay_len;
7638 size_t cfactor;
7639 int changed;
7641 /* Create vect of pointers to states ordered by num of transitions
7642 from the state (state with the maximum num is the first). */
7643 output_states_vect = 0;
7644 pass_states (automaton, add_states_vect_el);
7646 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7647 * automaton->insn_equiv_classes_num);
7648 min_issue_delay_vect = VEC_alloc (vect_el_t, heap, min_issue_delay_len);
7649 for (i = 0; i < min_issue_delay_len; i++)
7650 VEC_quick_push (vect_el_t, min_issue_delay_vect, -1);
7652 automaton->max_min_delay = 0;
7656 size_t state_no;
7658 changed = 0;
7660 for (state_no = 0; state_no < VEC_length (state_t, output_states_vect);
7661 state_no++)
7663 state_t s = VEC_index (state_t, output_states_vect, state_no);
7664 arc_t arc;
7666 for (arc = first_out_arc (s); arc; arc = next_out_arc (arc))
7668 int k;
7670 size_t asn = s->order_state_num
7671 * automaton->insn_equiv_classes_num
7672 + arc->insn->insn_equiv_class_num;
7674 if (VEC_index (vect_el_t, min_issue_delay_vect, asn))
7676 VEC_replace (vect_el_t, min_issue_delay_vect, asn, 0);
7677 changed = 1;
7680 for (k = 0; k < automaton->insn_equiv_classes_num; k++)
7682 size_t n0, n1;
7683 vect_el_t delay0, delay1;
7685 n0 = s->order_state_num
7686 * automaton->insn_equiv_classes_num
7687 + k;
7688 n1 = arc->to_state->order_state_num
7689 * automaton->insn_equiv_classes_num
7690 + k;
7691 delay0 = VEC_index (vect_el_t, min_issue_delay_vect, n0);
7692 delay1 = VEC_index (vect_el_t, min_issue_delay_vect, n1);
7693 if (delay1 != -1)
7695 if (arc->insn->insn_reserv_decl
7696 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7697 delay1++;
7698 if (delay1 < delay0 || delay0 == -1)
7700 VEC_replace (vect_el_t, min_issue_delay_vect, n0, delay1);
7701 changed = 1;
7708 while (changed);
7710 automaton->max_min_delay = 0;
7712 for (ainsn = automaton->ainsn_list; ainsn; ainsn = ainsn->next_ainsn)
7713 if (ainsn->first_ainsn_with_given_equivalence_num)
7715 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7717 state_t s = VEC_index (state_t, output_states_vect, i);
7718 size_t np = s->order_state_num
7719 * automaton->insn_equiv_classes_num
7720 + ainsn->insn_equiv_class_num;
7721 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, np);
7723 if (automaton->max_min_delay < x)
7724 automaton->max_min_delay = x;
7725 if (x == -1)
7726 VEC_replace (vect_el_t, min_issue_delay_vect, np, 0);
7730 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7731 fprintf (output_file, "static const ");
7732 output_range_type (output_file, 0, automaton->max_min_delay);
7733 fprintf (output_file, " ");
7734 output_min_issue_delay_vect_name (output_file, automaton);
7735 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7736 /* Compress the vector. */
7737 if (automaton->max_min_delay < 2)
7738 cfactor = 8;
7739 else if (automaton->max_min_delay < 4)
7740 cfactor = 4;
7741 else if (automaton->max_min_delay < 16)
7742 cfactor = 2;
7743 else
7744 cfactor = 1;
7745 automaton->min_issue_delay_table_compression_factor = cfactor;
7747 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7748 compressed_min_issue_delay_vect
7749 = VEC_alloc (vect_el_t, heap, compressed_min_issue_delay_len);
7751 for (i = 0; i < compressed_min_issue_delay_len; i++)
7752 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7754 for (i = 0; i < min_issue_delay_len; i++)
7756 size_t ci = i / cfactor;
7757 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7758 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7760 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7761 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7763 output_vect (compressed_min_issue_delay_vect);
7764 fprintf (output_file, "};\n\n");
7765 VEC_free (state_t, heap, output_states_vect);
7766 VEC_free (vect_el_t, heap, min_issue_delay_vect);
7767 VEC_free (vect_el_t, heap, compressed_min_issue_delay_vect);
7770 /* Form and output vector representing the locked states of
7771 AUTOMATON. */
7772 static void
7773 output_dead_lock_vect (automaton_t automaton)
7775 size_t i;
7776 arc_t arc;
7777 vla_hwint_t dead_lock_vect = 0;
7779 /* Create vect of pointers to states ordered by num of
7780 transitions from the state (state with the maximum num is the
7781 first). */
7782 automaton->locked_states = 0;
7783 output_states_vect = 0;
7784 pass_states (automaton, add_states_vect_el);
7786 VEC_safe_grow (vect_el_t, heap, dead_lock_vect,
7787 VEC_length (state_t, output_states_vect));
7788 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7790 state_t s = VEC_index (state_t, output_states_vect, i);
7791 arc = first_out_arc (s);
7792 gcc_assert (arc);
7793 if (next_out_arc (arc) == NULL
7794 && (arc->insn->insn_reserv_decl
7795 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7797 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7798 automaton->locked_states++;
7800 else
7801 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7803 if (automaton->locked_states == 0)
7804 return;
7806 fprintf (output_file, "/* Vector for locked state flags. */\n");
7807 fprintf (output_file, "static const ");
7808 output_range_type (output_file, 0, 1);
7809 fprintf (output_file, " ");
7810 output_dead_lock_vect_name (output_file, automaton);
7811 fprintf (output_file, "[] = {\n");
7812 output_vect (dead_lock_vect);
7813 fprintf (output_file, "};\n\n");
7814 VEC_free (state_t, heap, output_states_vect);
7815 VEC_free (vect_el_t, heap, dead_lock_vect);
7818 /* Form and output vector representing reserved units of the states of
7819 AUTOMATON. */
7820 static void
7821 output_reserved_units_table (automaton_t automaton)
7823 vla_hwint_t reserved_units_table = 0;
7824 int state_byte_size;
7825 int reserved_units_size;
7826 size_t n;
7827 int i;
7829 if (description->query_units_num == 0)
7830 return;
7832 /* Create vect of pointers to states. */
7833 output_states_vect = 0;
7834 pass_states (automaton, add_states_vect_el);
7835 /* Create vector. */
7836 state_byte_size = (description->query_units_num + 7) / 8;
7837 reserved_units_size = (VEC_length (state_t, output_states_vect)
7838 * state_byte_size);
7840 reserved_units_table = VEC_alloc (vect_el_t, heap, reserved_units_size);
7842 for (i = 0; i < reserved_units_size; i++)
7843 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7844 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7846 state_t s = VEC_index (state_t, output_states_vect, n);
7847 for (i = 0; i < description->units_num; i++)
7848 if (units_array [i]->query_p
7849 && first_cycle_unit_presence (s, i))
7851 int ri = (s->order_state_num * state_byte_size
7852 + units_array [i]->query_num / 8);
7853 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7855 x += 1 << (units_array [i]->query_num % 8);
7856 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7859 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7860 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7861 fprintf (output_file, "static const ");
7862 output_range_type (output_file, 0, 255);
7863 fprintf (output_file, " ");
7864 output_reserved_units_table_name (output_file, automaton);
7865 fprintf (output_file, "[] = {\n");
7866 output_vect (reserved_units_table);
7867 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7868 CPU_UNITS_QUERY_MACRO_NAME);
7870 VEC_free (state_t, heap, output_states_vect);
7871 VEC_free (vect_el_t, heap, reserved_units_table);
7874 /* The function outputs all tables representing DFA(s) used for fast
7875 pipeline hazards recognition. */
7876 static void
7877 output_tables (void)
7879 automaton_t automaton;
7881 for (automaton = description->first_automaton;
7882 automaton != NULL;
7883 automaton = automaton->next_automaton)
7885 output_translate_vect (automaton);
7886 output_trans_table (automaton);
7887 output_min_issue_delay_table (automaton);
7888 output_dead_lock_vect (automaton);
7889 output_reserved_units_table (automaton);
7891 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7892 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7893 if (collapse_flag)
7894 fprintf (output_file, "\n#define %s %d\n\n", COLLAPSE_NDFA_VALUE_NAME,
7895 DECL_INSN_RESERV (collapse_ndfa_insn_decl)->insn_num);
7898 /* The function outputs definition and value of PHR interface variable
7899 `max_insn_queue_index'. Its value is not less than maximal queue
7900 length needed for the insn scheduler. */
7901 static void
7902 output_max_insn_queue_index_def (void)
7904 int i, max, latency;
7905 decl_t decl;
7907 max = description->max_insn_reserv_cycles;
7908 for (i = 0; i < description->decls_num; i++)
7910 decl = description->decls [i];
7911 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7913 latency = DECL_INSN_RESERV (decl)->default_latency;
7914 if (latency > max)
7915 max = latency;
7917 else if (decl->mode == dm_bypass)
7919 latency = DECL_BYPASS (decl)->latency;
7920 if (latency > max)
7921 max = latency;
7924 for (i = 0; (1 << i) <= max; i++)
7926 gcc_assert (i >= 0);
7927 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7928 (1 << i) - 1);
7931 /* The function outputs switch cases for insn reservations using
7932 function *output_automata_list_code. */
7933 static void
7934 output_insn_code_cases (void (*output_automata_list_code)
7935 (automata_list_el_t))
7937 decl_t decl, decl2;
7938 int i, j;
7940 for (i = 0; i < description->decls_num; i++)
7942 decl = description->decls [i];
7943 if (decl->mode == dm_insn_reserv)
7944 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7946 for (i = 0; i < description->decls_num; i++)
7948 decl = description->decls [i];
7949 if (decl->mode == dm_insn_reserv
7950 && !DECL_INSN_RESERV (decl)->processed_p)
7952 for (j = i; j < description->decls_num; j++)
7954 decl2 = description->decls [j];
7955 if (decl2->mode == dm_insn_reserv
7956 && (DECL_INSN_RESERV (decl2)->important_automata_list
7957 == DECL_INSN_RESERV (decl)->important_automata_list))
7959 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7960 fprintf (output_file, " case %d: /* %s */\n",
7961 DECL_INSN_RESERV (decl2)->insn_num,
7962 DECL_INSN_RESERV (decl2)->name);
7965 (*output_automata_list_code)
7966 (DECL_INSN_RESERV (decl)->important_automata_list);
7972 /* The function outputs a code for evaluation of a minimal delay of
7973 issue of insns which have reservations in given AUTOMATA_LIST. */
7974 static void
7975 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7977 automata_list_el_t el;
7978 automaton_t automaton;
7980 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7982 automaton = el->automaton;
7983 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7984 output_min_issue_delay_vect_name (output_file, automaton);
7985 fprintf (output_file,
7986 (automaton->min_issue_delay_table_compression_factor != 1
7987 ? " [(" : " ["));
7988 output_translate_vect_name (output_file, automaton);
7989 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7990 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7991 output_chip_member_name (output_file, automaton);
7992 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7993 if (automaton->min_issue_delay_table_compression_factor == 1)
7994 fprintf (output_file, "];\n");
7995 else
7997 fprintf (output_file, ") / %d];\n",
7998 automaton->min_issue_delay_table_compression_factor);
7999 fprintf (output_file, " %s = (%s >> (8 - ((",
8000 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8001 output_translate_vect_name (output_file, automaton);
8002 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8003 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8004 output_chip_member_name (output_file, automaton);
8005 fprintf (output_file, " * %d)", automaton->insn_equiv_classes_num);
8006 fprintf
8007 (output_file, " %% %d + 1) * %d)) & %d;\n",
8008 automaton->min_issue_delay_table_compression_factor,
8009 8 / automaton->min_issue_delay_table_compression_factor,
8010 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
8011 - 1);
8013 if (el == automata_list)
8014 fprintf (output_file, " %s = %s;\n",
8015 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8016 else
8018 fprintf (output_file, " if (%s > %s)\n",
8019 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8020 fprintf (output_file, " %s = %s;\n",
8021 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
8024 fprintf (output_file, " break;\n\n");
8027 /* Output function `internal_min_issue_delay'. */
8028 static void
8029 output_internal_min_issue_delay_func (void)
8031 fprintf (output_file,
8032 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8033 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8034 CHIP_NAME, CHIP_PARAMETER_NAME);
8035 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
8036 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
8037 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8038 output_insn_code_cases (output_automata_list_min_issue_delay_code);
8039 fprintf (output_file,
8040 "\n default:\n %s = -1;\n break;\n }\n",
8041 RESULT_VARIABLE_NAME);
8042 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
8043 fprintf (output_file, "}\n\n");
8046 /* The function outputs a code changing state after issue of insns
8047 which have reservations in given AUTOMATA_LIST. */
8048 static void
8049 output_automata_list_transition_code (automata_list_el_t automata_list)
8051 automata_list_el_t el, next_el;
8053 fprintf (output_file, " {\n");
8054 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8055 for (el = automata_list;; el = next_el)
8057 next_el = el->next_automata_list_el;
8058 if (next_el == NULL)
8059 break;
8060 fprintf (output_file, " ");
8061 output_state_member_type (output_file, el->automaton);
8062 fprintf (output_file, " ");
8063 output_temp_chip_member_name (output_file, el->automaton);
8064 fprintf (output_file, ";\n");
8066 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
8067 if (comb_vect_p (el->automaton->trans_table))
8069 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8070 output_trans_base_vect_name (output_file, el->automaton);
8071 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8072 output_chip_member_name (output_file, el->automaton);
8073 fprintf (output_file, "] + ");
8074 output_translate_vect_name (output_file, el->automaton);
8075 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
8076 fprintf (output_file, " if (");
8077 output_trans_check_vect_name (output_file, el->automaton);
8078 fprintf (output_file, " [%s] != %s->",
8079 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
8080 output_chip_member_name (output_file, el->automaton);
8081 fprintf (output_file, ")\n");
8082 fprintf (output_file, " return %s (%s, %s);\n",
8083 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8084 CHIP_PARAMETER_NAME);
8085 fprintf (output_file, " else\n");
8086 fprintf (output_file, " ");
8087 if (el->next_automata_list_el != NULL)
8088 output_temp_chip_member_name (output_file, el->automaton);
8089 else
8091 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8092 output_chip_member_name (output_file, el->automaton);
8094 fprintf (output_file, " = ");
8095 output_trans_comb_vect_name (output_file, el->automaton);
8096 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
8098 else
8100 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
8101 output_trans_full_vect_name (output_file, el->automaton);
8102 fprintf (output_file, " [");
8103 output_translate_vect_name (output_file, el->automaton);
8104 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
8105 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8106 output_chip_member_name (output_file, el->automaton);
8107 fprintf (output_file, " * %d];\n",
8108 el->automaton->insn_equiv_classes_num);
8109 fprintf (output_file, " if (%s >= %d)\n",
8110 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
8111 fprintf (output_file, " return %s (%s, %s);\n",
8112 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8113 CHIP_PARAMETER_NAME);
8114 fprintf (output_file, " else\n ");
8115 if (el->next_automata_list_el != NULL)
8116 output_temp_chip_member_name (output_file, el->automaton);
8117 else
8119 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
8120 output_chip_member_name (output_file, el->automaton);
8122 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
8124 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
8125 for (el = automata_list;; el = next_el)
8127 next_el = el->next_automata_list_el;
8128 if (next_el == NULL)
8129 break;
8130 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
8131 output_chip_member_name (output_file, el->automaton);
8132 fprintf (output_file, " = ");
8133 output_temp_chip_member_name (output_file, el->automaton);
8134 fprintf (output_file, ";\n");
8136 fprintf (output_file, " return -1;\n");
8137 fprintf (output_file, " }\n");
8140 /* Output function `internal_state_transition'. */
8141 static void
8142 output_internal_trans_func (void)
8144 fprintf (output_file,
8145 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
8146 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8147 CHIP_NAME, CHIP_PARAMETER_NAME);
8148 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
8149 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8150 output_insn_code_cases (output_automata_list_transition_code);
8151 fprintf (output_file, "\n default:\n return -1;\n }\n");
8152 fprintf (output_file, "}\n\n");
8155 /* Output code
8157 if (insn != 0)
8159 insn_code = dfa_insn_code (insn);
8160 if (insn_code > DFA__ADVANCE_CYCLE)
8161 return code;
8163 else
8164 insn_code = DFA__ADVANCE_CYCLE;
8166 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
8167 code denotes CODE. */
8168 static void
8169 output_internal_insn_code_evaluation (const char *insn_name,
8170 const char *insn_code_name,
8171 int code)
8173 fprintf (output_file, "\n if (%s == 0)\n", insn_name);
8174 fprintf (output_file, " %s = %s;\n\n",
8175 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
8176 if (collapse_flag)
8178 fprintf (output_file, "\n else if (%s == const0_rtx)\n", insn_name);
8179 fprintf (output_file, " %s = %s;\n\n",
8180 insn_code_name, COLLAPSE_NDFA_VALUE_NAME);
8182 fprintf (output_file, "\n else\n {\n");
8183 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
8184 DFA_INSN_CODE_FUNC_NAME, insn_name);
8185 fprintf (output_file, " if (%s > %s)\n return %d;\n }\n",
8186 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
8190 /* This function outputs `dfa_insn_code' and its helper function
8191 `dfa_insn_code_enlarge'. */
8192 static void
8193 output_dfa_insn_code_func (void)
8195 /* Emacs c-mode gets really confused if there's a { or } in column 0
8196 inside a string, so don't do that. */
8197 fprintf (output_file, "\
8198 static void\n\
8199 dfa_insn_code_enlarge (int uid)\n\
8200 {\n\
8201 int i = %s;\n\
8202 %s = 2 * uid;\n\
8203 %s = XRESIZEVEC (int, %s,\n\
8204 %s);\n\
8205 for (; i < %s; i++)\n\
8206 %s[i] = -1;\n}\n\n",
8207 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8208 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8209 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8210 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8211 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
8212 DFA_INSN_CODES_VARIABLE_NAME);
8213 fprintf (output_file, "\
8214 static inline int\n%s (rtx %s)\n\
8215 {\n\
8216 int uid = INSN_UID (%s);\n\
8217 int %s;\n\n",
8218 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8219 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
8221 fprintf (output_file,
8222 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
8223 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8224 fprintf (output_file, " %s = %s[uid];\n",
8225 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8226 fprintf (output_file, "\
8227 if (%s < 0)\n\
8228 {\n\
8229 %s = %s (%s);\n\
8230 %s[uid] = %s;\n\
8231 }\n",
8232 INTERNAL_INSN_CODE_NAME,
8233 INTERNAL_INSN_CODE_NAME,
8234 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
8235 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
8236 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
8239 /* The function outputs PHR interface function `state_transition'. */
8240 static void
8241 output_trans_func (void)
8243 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8244 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8245 INSN_PARAMETER_NAME);
8246 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8247 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8248 INTERNAL_INSN_CODE_NAME, -1);
8249 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
8250 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
8253 /* Output function `min_issue_delay'. */
8254 static void
8255 output_min_issue_delay_func (void)
8257 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
8258 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
8259 INSN_PARAMETER_NAME);
8260 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
8261 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
8262 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
8263 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
8264 fprintf (output_file, " if (%s > %s)\n return 0;\n",
8265 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8266 fprintf (output_file, " }\n else\n %s = %s;\n",
8267 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8268 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
8269 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8270 CHIP_NAME, STATE_NAME);
8271 fprintf (output_file, "}\n\n");
8274 /* Output function `internal_dead_lock'. */
8275 static void
8276 output_internal_dead_lock_func (void)
8278 automaton_t automaton;
8280 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
8281 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8282 fprintf (output_file, "{\n");
8283 for (automaton = description->first_automaton;
8284 automaton != NULL;
8285 automaton = automaton->next_automaton)
8286 if (automaton->locked_states)
8288 fprintf (output_file, " if (");
8289 output_dead_lock_vect_name (output_file, automaton);
8290 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8291 output_chip_member_name (output_file, automaton);
8292 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8294 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8297 /* The function outputs PHR interface function `state_dead_lock_p'. */
8298 static void
8299 output_dead_lock_func (void)
8301 fprintf (output_file, "int\n%s (%s %s)\n",
8302 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8303 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8304 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8307 /* Output function `internal_reset'. */
8308 static void
8309 output_internal_reset_func (void)
8311 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8312 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8313 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8314 CHIP_PARAMETER_NAME, CHIP_NAME);
8317 /* The function outputs PHR interface function `state_size'. */
8318 static void
8319 output_size_func (void)
8321 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8322 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8325 /* The function outputs PHR interface function `state_reset'. */
8326 static void
8327 output_reset_func (void)
8329 fprintf (output_file, "void\n%s (%s %s)\n",
8330 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8331 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8332 CHIP_NAME, STATE_NAME);
8335 /* Output function `min_insn_conflict_delay'. */
8336 static void
8337 output_min_insn_conflict_delay_func (void)
8339 fprintf (output_file,
8340 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8341 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8342 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8343 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8344 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8345 INTERNAL_INSN2_CODE_NAME);
8346 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8347 INTERNAL_INSN_CODE_NAME, 0);
8348 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8349 INTERNAL_INSN2_CODE_NAME, 0);
8350 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8351 CHIP_NAME, STATE_NAME, CHIP_NAME);
8352 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8353 fprintf (output_file, " transition = %s (%s, &%s);\n",
8354 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8355 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8356 fprintf (output_file, " return %s (%s, &%s);\n",
8357 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8358 CHIP_NAME);
8359 fprintf (output_file, "}\n\n");
8362 /* Output the array holding default latency values. These are used in
8363 insn_latency and maximal_insn_latency function implementations. */
8364 static void
8365 output_default_latencies (void)
8367 int i, j, col;
8368 decl_t decl;
8369 const char *tabletype = "unsigned char";
8371 /* Find the smallest integer type that can hold all the default
8372 latency values. */
8373 for (i = 0; i < description->decls_num; i++)
8374 if (description->decls[i]->mode == dm_insn_reserv)
8376 decl = description->decls[i];
8377 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8378 && tabletype[0] != 'i') /* Don't shrink it. */
8379 tabletype = "unsigned short";
8380 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8381 tabletype = "int";
8384 fprintf (output_file, " static const %s default_latencies[] =\n {",
8385 tabletype);
8387 for (i = 0, j = 0, col = 7; i < description->normal_decls_num; i++)
8388 if (description->decls[i]->mode == dm_insn_reserv)
8390 if ((col = (col+1) % 8) == 0)
8391 fputs ("\n ", output_file);
8392 decl = description->decls[i];
8393 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8394 fprintf (output_file, "% 4d,",
8395 DECL_INSN_RESERV (decl)->default_latency);
8397 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8398 fputs ("\n };\n", output_file);
8401 /* Output function `internal_insn_latency'. */
8402 static void
8403 output_internal_insn_latency_func (void)
8405 int i;
8406 decl_t decl;
8407 struct bypass_decl *bypass;
8409 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",
8410 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8411 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8412 INSN2_PARAMETER_NAME);
8413 fprintf (output_file, "{\n");
8415 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8417 fputs (" return 0;\n}\n\n", output_file);
8418 return;
8421 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8422 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8423 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8425 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8426 for (i = 0; i < description->decls_num; i++)
8427 if (description->decls[i]->mode == dm_insn_reserv
8428 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8430 decl = description->decls [i];
8431 fprintf (output_file,
8432 " case %d:\n switch (%s)\n {\n",
8433 DECL_INSN_RESERV (decl)->insn_num,
8434 INTERNAL_INSN2_CODE_NAME);
8435 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8436 bypass != NULL;
8437 bypass = bypass->next)
8439 gcc_assert (bypass->in_insn_reserv->insn_num
8440 != (DECL_INSN_RESERV
8441 (advance_cycle_insn_decl)->insn_num));
8442 fprintf (output_file, " case %d:\n",
8443 bypass->in_insn_reserv->insn_num);
8444 for (;;)
8446 if (bypass->bypass_guard_name == NULL)
8448 gcc_assert (bypass->next == NULL
8449 || (bypass->in_insn_reserv
8450 != bypass->next->in_insn_reserv));
8451 fprintf (output_file, " return %d;\n",
8452 bypass->latency);
8454 else
8456 fprintf (output_file,
8457 " if (%s (%s, %s))\n",
8458 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8459 INSN2_PARAMETER_NAME);
8460 fprintf (output_file, " return %d;\n",
8461 bypass->latency);
8463 if (bypass->next == NULL
8464 || bypass->in_insn_reserv != bypass->next->in_insn_reserv)
8465 break;
8466 bypass = bypass->next;
8468 if (bypass->bypass_guard_name != NULL)
8469 fprintf (output_file, " break;\n");
8471 fputs (" }\n break;\n", output_file);
8474 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8475 INTERNAL_INSN_CODE_NAME);
8478 /* Output function `internal_maximum_insn_latency'. */
8479 static void
8480 output_internal_maximal_insn_latency_func (void)
8482 decl_t decl;
8483 struct bypass_decl *bypass;
8484 int i;
8485 int max;
8487 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8488 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8489 INSN_PARAMETER_NAME);
8490 fprintf (output_file, "{\n");
8492 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8494 fputs (" return 0;\n}\n\n", output_file);
8495 return;
8498 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8499 for (i = 0; i < description->decls_num; i++)
8500 if (description->decls[i]->mode == dm_insn_reserv
8501 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8503 decl = description->decls [i];
8504 max = DECL_INSN_RESERV (decl)->default_latency;
8505 fprintf (output_file,
8506 " case %d: {",
8507 DECL_INSN_RESERV (decl)->insn_num);
8508 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8509 bypass != NULL;
8510 bypass = bypass->next)
8512 if (bypass->latency > max)
8513 max = bypass->latency;
8515 fprintf (output_file, " return %d; }\n break;\n", max);
8518 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8519 INTERNAL_INSN_CODE_NAME);
8522 /* The function outputs PHR interface function `insn_latency'. */
8523 static void
8524 output_insn_latency_func (void)
8526 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8527 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8528 fprintf (output_file, "{\n int %s, %s;\n",
8529 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8530 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8531 INTERNAL_INSN_CODE_NAME, 0);
8532 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8533 INTERNAL_INSN2_CODE_NAME, 0);
8534 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8535 INTERNAL_INSN_LATENCY_FUNC_NAME,
8536 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8537 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8540 /* The function outputs PHR interface function `maximal_insn_latency'. */
8541 static void
8542 output_maximal_insn_latency_func (void)
8544 fprintf (output_file, "int\n%s (rtx %s)\n",
8545 "maximal_insn_latency", INSN_PARAMETER_NAME);
8546 fprintf (output_file, "{\n int %s;\n",
8547 INTERNAL_INSN_CODE_NAME);
8548 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8549 INTERNAL_INSN_CODE_NAME, 0);
8550 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8551 "internal_maximal_insn_latency",
8552 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8555 /* The function outputs PHR interface function `print_reservation'. */
8556 static void
8557 output_print_reservation_func (void)
8559 decl_t decl;
8560 int i, j;
8562 fprintf (output_file,
8563 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8564 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8565 INSN_PARAMETER_NAME);
8567 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8569 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8570 NOTHING_NAME, FILE_PARAMETER_NAME);
8571 return;
8575 fputs (" static const char *const reservation_names[] =\n {",
8576 output_file);
8578 for (i = 0, j = 0; i < description->normal_decls_num; i++)
8580 decl = description->decls [i];
8581 if (decl->mode == dm_insn_reserv)
8583 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8584 j++;
8586 fprintf (output_file, "\n \"%s\",",
8587 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8588 finish_regexp_representation ();
8591 gcc_assert (j == description->insns_num - (collapse_flag ? 2 : 1));
8593 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8594 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8596 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8597 INSN_PARAMETER_NAME,
8598 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8599 fprintf (output_file, " else\n\
8600 {\n\
8601 %s = %s (%s);\n\
8602 if (%s > %s)\n\
8603 %s = %s;\n\
8604 }\n",
8605 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8606 INSN_PARAMETER_NAME,
8607 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8608 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8610 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8611 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8614 /* The following function is used to sort unit declaration by their
8615 names. */
8616 static int
8617 units_cmp (const void *unit1, const void *unit2)
8619 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8620 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8622 return strcmp (u1->name, u2->name);
8625 /* The following macro value is name of struct containing unit name
8626 and unit code. */
8627 #define NAME_CODE_STRUCT_NAME "name_code"
8629 /* The following macro value is name of table of struct name_code. */
8630 #define NAME_CODE_TABLE_NAME "name_code_table"
8632 /* The following macro values are member names for struct name_code. */
8633 #define NAME_MEMBER_NAME "name"
8634 #define CODE_MEMBER_NAME "code"
8636 /* The following macro values are local variable names for function
8637 `get_cpu_unit_code'. */
8638 #define CMP_VARIABLE_NAME "cmp"
8639 #define LOW_VARIABLE_NAME "l"
8640 #define MIDDLE_VARIABLE_NAME "m"
8641 #define HIGH_VARIABLE_NAME "h"
8643 /* The following function outputs function to obtain internal cpu unit
8644 code by the cpu unit name. */
8645 static void
8646 output_get_cpu_unit_code_func (void)
8648 int i;
8649 unit_decl_t *units;
8651 fprintf (output_file, "int\n%s (const char *%s)\n",
8652 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8653 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8654 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8655 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8656 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8657 fprintf (output_file, " static struct %s %s [] =\n {\n",
8658 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8659 units = XNEWVEC (unit_decl_t, description->units_num);
8660 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8661 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8662 for (i = 0; i < description->units_num; i++)
8663 if (units [i]->query_p)
8664 fprintf (output_file, " {\"%s\", %d},\n",
8665 units[i]->name, units[i]->query_num);
8666 fprintf (output_file, " };\n\n");
8667 fprintf (output_file, " /* The following is binary search: */\n");
8668 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8669 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8670 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8671 fprintf (output_file, " while (%s <= %s)\n {\n",
8672 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8673 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8674 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8675 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8676 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8677 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8678 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8679 fprintf (output_file, " %s = %s - 1;\n",
8680 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8681 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8682 fprintf (output_file, " %s = %s + 1;\n",
8683 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8684 fprintf (output_file, " else\n");
8685 fprintf (output_file, " return %s [%s].%s;\n }\n",
8686 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8687 fprintf (output_file, " return -1;\n}\n\n");
8688 free (units);
8691 /* The following function outputs function to check reservation of cpu
8692 unit (its internal code will be passed as the function argument) in
8693 given cpu state. */
8694 static void
8695 output_cpu_unit_reservation_p (void)
8697 automaton_t automaton;
8699 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8700 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8701 STATE_TYPE_NAME, STATE_NAME,
8702 CPU_CODE_PARAMETER_NAME);
8703 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8704 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8705 description->query_units_num);
8706 if (description->query_units_num > 0)
8707 for (automaton = description->first_automaton;
8708 automaton != NULL;
8709 automaton = automaton->next_automaton)
8711 fprintf (output_file, " if ((");
8712 output_reserved_units_table_name (output_file, automaton);
8713 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8714 output_chip_member_name (output_file, automaton);
8715 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8716 (description->query_units_num + 7) / 8,
8717 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8718 fprintf (output_file, " return 1;\n");
8720 fprintf (output_file, " return 0;\n}\n\n");
8723 /* The following function outputs a function to check if insn
8724 has a dfa reservation. */
8725 static void
8726 output_insn_has_dfa_reservation_p (void)
8728 fprintf (output_file,
8729 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8730 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8731 INSN_PARAMETER_NAME);
8733 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8735 fprintf (output_file, " return false;\n}\n\n");
8736 return;
8739 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8741 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8742 INSN_PARAMETER_NAME,
8743 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8744 fprintf (output_file, " else\n\
8745 {\n\
8746 %s = %s (%s);\n\
8747 if (%s > %s)\n\
8748 %s = %s;\n\
8749 }\n\n",
8750 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8751 INSN_PARAMETER_NAME,
8752 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8753 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8755 fprintf (output_file, " return %s != %s;\n}\n\n",
8756 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8759 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8760 and 'dfa_clear_single_insn_cache'. */
8761 static void
8762 output_dfa_clean_insn_cache_func (void)
8764 fprintf (output_file,
8765 "void\n%s (void)\n{\n int %s;\n\n",
8766 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8767 fprintf (output_file,
8768 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8769 I_VARIABLE_NAME, I_VARIABLE_NAME,
8770 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8771 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8773 fprintf (output_file,
8774 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8775 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8776 I_VARIABLE_NAME);
8777 fprintf (output_file,
8778 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8779 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8780 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8781 I_VARIABLE_NAME);
8784 /* The function outputs PHR interface function `dfa_start'. */
8785 static void
8786 output_dfa_start_func (void)
8788 fprintf (output_file,
8789 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8790 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8791 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8792 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8793 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8796 /* The function outputs PHR interface function `dfa_finish'. */
8797 static void
8798 output_dfa_finish_func (void)
8800 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8801 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8806 /* The page contains code for output description file (readable
8807 representation of original description and generated DFA(s). */
8809 /* The function outputs string representation of IR reservation. */
8810 static void
8811 output_regexp (regexp_t regexp)
8813 fprintf (output_description_file, "%s", regexp_representation (regexp));
8814 finish_regexp_representation ();
8817 /* Output names of units in LIST separated by comma. */
8818 static void
8819 output_unit_set_el_list (unit_set_el_t list)
8821 unit_set_el_t el;
8823 for (el = list; el != NULL; el = el->next_unit_set_el)
8825 if (el != list)
8826 fprintf (output_description_file, ", ");
8827 fprintf (output_description_file, "%s", el->unit_decl->name);
8831 /* Output patterns in LIST separated by comma. */
8832 static void
8833 output_pattern_set_el_list (pattern_set_el_t list)
8835 pattern_set_el_t el;
8836 int i;
8838 for (el = list; el != NULL; el = el->next_pattern_set_el)
8840 if (el != list)
8841 fprintf (output_description_file, ", ");
8842 for (i = 0; i < el->units_num; i++)
8843 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8844 el->unit_decls [i]->name);
8848 /* The function outputs string representation of IR define_reservation
8849 and define_insn_reservation. */
8850 static void
8851 output_description (void)
8853 decl_t decl;
8854 int i;
8856 for (i = 0; i < description->decls_num; i++)
8858 decl = description->decls [i];
8859 if (decl->mode == dm_unit)
8861 if (DECL_UNIT (decl)->excl_list != NULL)
8863 fprintf (output_description_file, "unit %s exclusion_set: ",
8864 DECL_UNIT (decl)->name);
8865 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8866 fprintf (output_description_file, "\n");
8868 if (DECL_UNIT (decl)->presence_list != NULL)
8870 fprintf (output_description_file, "unit %s presence_set: ",
8871 DECL_UNIT (decl)->name);
8872 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8873 fprintf (output_description_file, "\n");
8875 if (DECL_UNIT (decl)->final_presence_list != NULL)
8877 fprintf (output_description_file, "unit %s final_presence_set: ",
8878 DECL_UNIT (decl)->name);
8879 output_pattern_set_el_list
8880 (DECL_UNIT (decl)->final_presence_list);
8881 fprintf (output_description_file, "\n");
8883 if (DECL_UNIT (decl)->absence_list != NULL)
8885 fprintf (output_description_file, "unit %s absence_set: ",
8886 DECL_UNIT (decl)->name);
8887 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8888 fprintf (output_description_file, "\n");
8890 if (DECL_UNIT (decl)->final_absence_list != NULL)
8892 fprintf (output_description_file, "unit %s final_absence_set: ",
8893 DECL_UNIT (decl)->name);
8894 output_pattern_set_el_list
8895 (DECL_UNIT (decl)->final_absence_list);
8896 fprintf (output_description_file, "\n");
8900 fprintf (output_description_file, "\n");
8901 for (i = 0; i < description->normal_decls_num; i++)
8903 decl = description->decls [i];
8904 if (decl->mode == dm_reserv)
8906 fprintf (output_description_file, "reservation %s: ",
8907 DECL_RESERV (decl)->name);
8908 output_regexp (DECL_RESERV (decl)->regexp);
8909 fprintf (output_description_file, "\n");
8911 else if (decl->mode == dm_insn_reserv)
8913 fprintf (output_description_file, "insn reservation %s ",
8914 DECL_INSN_RESERV (decl)->name);
8915 print_rtl (output_description_file,
8916 DECL_INSN_RESERV (decl)->condexp);
8917 fprintf (output_description_file, ": ");
8918 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8919 fprintf (output_description_file, "\n");
8921 else if (decl->mode == dm_bypass)
8922 fprintf (output_description_file, "bypass %d %s %s\n",
8923 DECL_BYPASS (decl)->latency,
8924 DECL_BYPASS (decl)->out_pattern,
8925 DECL_BYPASS (decl)->in_pattern);
8927 fprintf (output_description_file, "\n\f\n");
8930 /* The function outputs name of AUTOMATON. */
8931 static void
8932 output_automaton_name (FILE *f, automaton_t automaton)
8934 if (automaton->corresponding_automaton_decl == NULL)
8935 fprintf (f, "#%d", automaton->automaton_order_num);
8936 else
8937 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8940 /* Maximal length of line for pretty printing into description
8941 file. */
8942 #define MAX_LINE_LENGTH 70
8944 /* The function outputs units name belonging to AUTOMATON. */
8945 static void
8946 output_automaton_units (automaton_t automaton)
8948 decl_t decl;
8949 const char *name;
8950 int curr_line_length;
8951 int there_is_an_automaton_unit;
8952 int i;
8954 fprintf (output_description_file, "\n Corresponding units:\n");
8955 fprintf (output_description_file, " ");
8956 curr_line_length = 4;
8957 there_is_an_automaton_unit = 0;
8958 for (i = 0; i < description->decls_num; i++)
8960 decl = description->decls [i];
8961 if (decl->mode == dm_unit
8962 && (DECL_UNIT (decl)->corresponding_automaton_num
8963 == automaton->automaton_order_num))
8965 there_is_an_automaton_unit = 1;
8966 name = DECL_UNIT (decl)->name;
8967 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8969 curr_line_length = strlen (name) + 4;
8970 fprintf (output_description_file, "\n ");
8972 else
8974 curr_line_length += strlen (name) + 1;
8975 fprintf (output_description_file, " ");
8977 fprintf (output_description_file, "%s", name);
8980 if (!there_is_an_automaton_unit)
8981 fprintf (output_description_file, "<None>");
8982 fprintf (output_description_file, "\n\n");
8985 /* The following variable is used for forming array of all possible cpu unit
8986 reservations described by the current DFA state. */
8987 static VEC(reserv_sets_t, heap) *state_reservs;
8989 /* The function forms `state_reservs' for STATE. */
8990 static void
8991 add_state_reservs (state_t state)
8993 alt_state_t curr_alt_state;
8995 if (state->component_states != NULL)
8996 for (curr_alt_state = state->component_states;
8997 curr_alt_state != NULL;
8998 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8999 add_state_reservs (curr_alt_state->state);
9000 else
9001 VEC_safe_push (reserv_sets_t, heap, state_reservs, state->reservs);
9004 /* The function outputs readable representation of all out arcs of
9005 STATE. */
9006 static void
9007 output_state_arcs (state_t state)
9009 arc_t arc;
9010 ainsn_t ainsn;
9011 const char *insn_name;
9012 int curr_line_length;
9014 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
9016 ainsn = arc->insn;
9017 gcc_assert (ainsn->first_insn_with_same_reservs);
9018 fprintf (output_description_file, " ");
9019 curr_line_length = 7;
9020 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
9023 insn_name = ainsn->insn_reserv_decl->name;
9024 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
9026 if (ainsn != arc->insn)
9028 fprintf (output_description_file, ",\n ");
9029 curr_line_length = strlen (insn_name) + 6;
9031 else
9032 curr_line_length += strlen (insn_name);
9034 else
9036 curr_line_length += strlen (insn_name);
9037 if (ainsn != arc->insn)
9039 curr_line_length += 2;
9040 fprintf (output_description_file, ", ");
9043 fprintf (output_description_file, "%s", insn_name);
9044 ainsn = ainsn->next_same_reservs_insn;
9046 while (ainsn != NULL);
9047 fprintf (output_description_file, " %d \n",
9048 arc->to_state->order_state_num);
9050 fprintf (output_description_file, "\n");
9053 /* The following function is used for sorting possible cpu unit
9054 reservation of a DFA state. */
9055 static int
9056 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
9058 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
9059 *(const_reserv_sets_t const*) reservs_ptr_2);
9062 /* The following function is used for sorting possible cpu unit
9063 reservation of a DFA state. */
9064 static void
9065 remove_state_duplicate_reservs (void)
9067 size_t i, j;
9069 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
9070 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
9071 VEC_index (reserv_sets_t, state_reservs, i)))
9073 j++;
9074 VEC_replace (reserv_sets_t, state_reservs, j,
9075 VEC_index (reserv_sets_t, state_reservs, i));
9077 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
9080 /* The following function output readable representation of DFA(s)
9081 state used for fast recognition of pipeline hazards. State is
9082 described by possible (current and scheduled) cpu unit
9083 reservations. */
9084 static void
9085 output_state (state_t state)
9087 size_t i;
9089 state_reservs = 0;
9091 fprintf (output_description_file, " State #%d", state->order_state_num);
9092 fprintf (output_description_file,
9093 state->new_cycle_p ? " (new cycle)\n" : "\n");
9094 add_state_reservs (state);
9095 VEC_qsort (reserv_sets_t, state_reservs, state_reservs_cmp);
9096 remove_state_duplicate_reservs ();
9097 for (i = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
9099 fprintf (output_description_file, " ");
9100 output_reserv_sets (output_description_file,
9101 VEC_index (reserv_sets_t, state_reservs, i));
9102 fprintf (output_description_file, "\n");
9104 fprintf (output_description_file, "\n");
9105 output_state_arcs (state);
9106 VEC_free (reserv_sets_t, heap, state_reservs);
9109 /* The following function output readable representation of
9110 DFAs used for fast recognition of pipeline hazards. */
9111 static void
9112 output_automaton_descriptions (void)
9114 automaton_t automaton;
9116 for (automaton = description->first_automaton;
9117 automaton != NULL;
9118 automaton = automaton->next_automaton)
9120 fprintf (output_description_file, "\nAutomaton ");
9121 output_automaton_name (output_description_file, automaton);
9122 fprintf (output_description_file, "\n");
9123 output_automaton_units (automaton);
9124 pass_states (automaton, output_state);
9130 /* The page contains top level function for generation DFA(s) used for
9131 PHR. */
9133 /* The function outputs statistics about work of different phases of
9134 DFA generator. */
9135 static void
9136 output_statistics (FILE *f)
9138 automaton_t automaton;
9139 int states_num;
9140 #ifndef NDEBUG
9141 int transition_comb_vect_els = 0;
9142 int transition_full_vect_els = 0;
9143 int min_issue_delay_vect_els = 0;
9144 int locked_states = 0;
9145 #endif
9147 for (automaton = description->first_automaton;
9148 automaton != NULL;
9149 automaton = automaton->next_automaton)
9151 fprintf (f, "\nAutomaton ");
9152 output_automaton_name (f, automaton);
9153 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
9154 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
9155 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
9156 automaton->DFA_states_num, automaton->DFA_arcs_num);
9157 states_num = automaton->DFA_states_num;
9158 if (!no_minimization_flag)
9160 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
9161 automaton->minimal_DFA_states_num,
9162 automaton->minimal_DFA_arcs_num);
9163 states_num = automaton->minimal_DFA_states_num;
9165 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
9166 description->insns_num, automaton->insn_equiv_classes_num);
9167 fprintf (f, " %d locked states\n", automaton->locked_states);
9168 #ifndef NDEBUG
9169 fprintf
9170 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
9171 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
9172 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
9173 (comb_vect_p (automaton->trans_table)
9174 ? "use comb vect" : "use simple vect"));
9175 fprintf
9176 (f, "%5ld min delay table els, compression factor %d\n",
9177 (long) states_num * automaton->insn_equiv_classes_num,
9178 automaton->min_issue_delay_table_compression_factor);
9179 transition_comb_vect_els
9180 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
9181 transition_full_vect_els
9182 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
9183 min_issue_delay_vect_els
9184 += states_num * automaton->insn_equiv_classes_num;
9185 locked_states
9186 += automaton->locked_states;
9187 #endif
9189 #ifndef NDEBUG
9190 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
9191 allocated_states_num, allocated_arcs_num);
9192 fprintf (f, "%5d all allocated alternative states\n",
9193 allocated_alt_states_num);
9194 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
9195 transition_comb_vect_els, transition_full_vect_els);
9196 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
9197 fprintf (f, "%5d all locked states\n", locked_states);
9198 #endif
9201 /* The function output times of work of different phases of DFA
9202 generator. */
9203 static void
9204 output_time_statistics (FILE *f)
9206 fprintf (f, "\n transformation: ");
9207 print_active_time (f, transform_time);
9208 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
9209 print_active_time (f, NDFA_time);
9210 if (ndfa_flag)
9212 fprintf (f, ", NDFA -> DFA: ");
9213 print_active_time (f, NDFA_to_DFA_time);
9215 fprintf (f, "\n DFA minimization: ");
9216 print_active_time (f, minimize_time);
9217 fprintf (f, ", making insn equivalence: ");
9218 print_active_time (f, equiv_time);
9219 fprintf (f, "\n all automaton generation: ");
9220 print_active_time (f, automaton_generation_time);
9221 fprintf (f, ", output: ");
9222 print_active_time (f, output_time);
9223 fprintf (f, "\n");
9226 /* The function generates DFA (deterministic finite state automaton)
9227 for fast recognition of pipeline hazards. No errors during
9228 checking must be fixed before this function call. */
9229 static void
9230 generate (void)
9232 automata_num = split_argument;
9233 if (description->units_num < automata_num)
9234 automata_num = description->units_num;
9235 initiate_states ();
9236 initiate_arcs ();
9237 initiate_automata_lists ();
9238 initiate_pass_states ();
9239 initiate_excl_sets ();
9240 initiate_presence_absence_pattern_sets ();
9241 automaton_generation_time = create_ticker ();
9242 create_automata ();
9243 ticker_off (&automaton_generation_time);
9248 /* This page mainly contains top level functions of pipeline hazards
9249 description translator. */
9251 /* The following macro value is suffix of name of description file of
9252 pipeline hazards description translator. */
9253 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
9255 /* The function returns suffix of given file name. The returned
9256 string can not be changed. */
9257 static const char *
9258 file_name_suffix (const char *file_name)
9260 const char *last_period;
9262 for (last_period = NULL; *file_name != '\0'; file_name++)
9263 if (*file_name == '.')
9264 last_period = file_name;
9265 return (last_period == NULL ? file_name : last_period);
9268 /* The function returns base name of given file name, i.e. pointer to
9269 first char after last `/' (or `\' for WIN32) in given file name,
9270 given file name itself if the directory name is absent. The
9271 returned string can not be changed. */
9272 static const char *
9273 base_file_name (const char *file_name)
9275 int directory_name_length;
9277 directory_name_length = strlen (file_name);
9278 #ifdef WIN32
9279 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
9280 && file_name[directory_name_length] != '\\')
9281 #else
9282 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
9283 #endif
9284 directory_name_length--;
9285 return file_name + directory_name_length + 1;
9288 /* The following is top level function to initialize the work of
9289 pipeline hazards description translator. */
9290 static void
9291 initiate_automaton_gen (int argc, char **argv)
9293 const char *base_name;
9294 int i;
9296 ndfa_flag = 0;
9297 split_argument = 0; /* default value */
9298 no_minimization_flag = 0;
9299 time_flag = 0;
9300 stats_flag = 0;
9301 v_flag = 0;
9302 w_flag = 0;
9303 progress_flag = 0;
9304 for (i = 2; i < argc; i++)
9305 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9306 no_minimization_flag = 1;
9307 else if (strcmp (argv [i], TIME_OPTION) == 0)
9308 time_flag = 1;
9309 else if (strcmp (argv [i], STATS_OPTION) == 0)
9310 stats_flag = 1;
9311 else if (strcmp (argv [i], V_OPTION) == 0)
9312 v_flag = 1;
9313 else if (strcmp (argv [i], W_OPTION) == 0)
9314 w_flag = 1;
9315 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9316 ndfa_flag = 1;
9317 else if (strcmp (argv [i], COLLAPSE_OPTION) == 0)
9318 collapse_flag = 1;
9319 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9320 progress_flag = 1;
9321 else if (strcmp (argv [i], "-split") == 0)
9323 if (i + 1 >= argc)
9324 fatal ("-split has no argument.");
9325 fatal ("option `-split' has not been implemented yet\n");
9326 /* split_argument = atoi (argument_vect [i + 1]); */
9329 /* Initialize IR storage. */
9330 obstack_init (&irp);
9331 initiate_automaton_decl_table ();
9332 initiate_insn_decl_table ();
9333 initiate_decl_table ();
9334 output_file = stdout;
9335 output_description_file = NULL;
9336 base_name = base_file_name (argv[1]);
9337 obstack_grow (&irp, base_name,
9338 strlen (base_name) - strlen (file_name_suffix (base_name)));
9339 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9340 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9341 obstack_1grow (&irp, '\0');
9342 output_description_file_name = obstack_base (&irp);
9343 obstack_finish (&irp);
9346 /* The following function checks existence at least one arc marked by
9347 each insn. */
9348 static void
9349 check_automata_insn_issues (void)
9351 automaton_t automaton;
9352 ainsn_t ainsn, reserv_ainsn;
9354 for (automaton = description->first_automaton;
9355 automaton != NULL;
9356 automaton = automaton->next_automaton)
9358 for (ainsn = automaton->ainsn_list;
9359 ainsn != NULL;
9360 ainsn = ainsn->next_ainsn)
9361 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p
9362 && ainsn != automaton->collapse_ainsn)
9364 for (reserv_ainsn = ainsn;
9365 reserv_ainsn != NULL;
9366 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9367 if (automaton->corresponding_automaton_decl != NULL)
9369 if (!w_flag)
9370 error ("Automaton `%s': Insn `%s' will never be issued",
9371 automaton->corresponding_automaton_decl->name,
9372 reserv_ainsn->insn_reserv_decl->name);
9373 else
9374 warning ("Automaton `%s': Insn `%s' will never be issued",
9375 automaton->corresponding_automaton_decl->name,
9376 reserv_ainsn->insn_reserv_decl->name);
9378 else
9380 if (!w_flag)
9381 error ("Insn `%s' will never be issued",
9382 reserv_ainsn->insn_reserv_decl->name);
9383 else
9384 warning ("Insn `%s' will never be issued",
9385 reserv_ainsn->insn_reserv_decl->name);
9391 /* The following vla is used for storing pointers to all achieved
9392 states. */
9393 static VEC(state_t, heap) *automaton_states;
9395 /* This function is called by function pass_states to add an achieved
9396 STATE. */
9397 static void
9398 add_automaton_state (state_t state)
9400 VEC_safe_push (state_t, heap, automaton_states, state);
9403 /* The following function forms list of important automata (whose
9404 states may be changed after the insn issue) for each insn. */
9405 static void
9406 form_important_insn_automata_lists (void)
9408 automaton_t automaton;
9409 decl_t decl;
9410 ainsn_t ainsn;
9411 arc_t arc;
9412 int i;
9413 size_t n;
9415 automaton_states = 0;
9416 /* Mark important ainsns. */
9417 for (automaton = description->first_automaton;
9418 automaton != NULL;
9419 automaton = automaton->next_automaton)
9421 VEC_truncate (state_t, automaton_states, 0);
9422 pass_states (automaton, add_automaton_state);
9423 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9425 state_t s = VEC_index (state_t, automaton_states, n);
9426 for (arc = first_out_arc (s);
9427 arc != NULL;
9428 arc = next_out_arc (arc))
9429 if (arc->to_state != s)
9431 gcc_assert (arc->insn->first_insn_with_same_reservs);
9432 for (ainsn = arc->insn;
9433 ainsn != NULL;
9434 ainsn = ainsn->next_same_reservs_insn)
9435 ainsn->important_p = TRUE;
9439 VEC_free (state_t, heap, automaton_states);
9441 /* Create automata sets for the insns. */
9442 for (i = 0; i < description->decls_num; i++)
9444 decl = description->decls [i];
9445 if (decl->mode == dm_insn_reserv)
9447 automata_list_start ();
9448 for (automaton = description->first_automaton;
9449 automaton != NULL;
9450 automaton = automaton->next_automaton)
9451 for (ainsn = automaton->ainsn_list;
9452 ainsn != NULL;
9453 ainsn = ainsn->next_ainsn)
9454 if (ainsn->important_p
9455 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9457 automata_list_add (automaton);
9458 break;
9460 DECL_INSN_RESERV (decl)->important_automata_list
9461 = automata_list_finish ();
9467 /* The following is top level function to generate automat(a,on) for
9468 fast recognition of pipeline hazards. */
9469 static void
9470 expand_automata (void)
9472 int i;
9474 description = XCREATENODEVAR (struct description,
9475 sizeof (struct description)
9476 /* Two entries for special insns. */
9477 + sizeof (decl_t) * (VEC_length (decl_t, decls) + 1));
9478 description->decls_num = VEC_length (decl_t, decls);
9479 description->normal_decls_num = description->decls_num;
9480 description->query_units_num = 0;
9481 for (i = 0; i < description->decls_num; i++)
9483 description->decls [i] = VEC_index (decl_t, decls, i);
9484 if (description->decls [i]->mode == dm_unit
9485 && DECL_UNIT (description->decls [i])->query_p)
9486 DECL_UNIT (description->decls [i])->query_num
9487 = description->query_units_num++;
9489 all_time = create_ticker ();
9490 check_time = create_ticker ();
9491 if (progress_flag)
9492 fprintf (stderr, "Check description...");
9493 check_all_description ();
9494 if (progress_flag)
9495 fprintf (stderr, "done\n");
9496 ticker_off (&check_time);
9497 generation_time = create_ticker ();
9498 if (!have_error)
9500 transform_insn_regexps ();
9501 check_unit_distributions_to_automata ();
9503 if (!have_error)
9505 generate ();
9506 check_automata_insn_issues ();
9508 if (!have_error)
9510 form_important_insn_automata_lists ();
9512 ticker_off (&generation_time);
9515 /* The following is top level function to output PHR and to finish
9516 work with pipeline description translator. */
9517 static void
9518 write_automata (void)
9520 output_time = create_ticker ();
9521 if (progress_flag)
9522 fprintf (stderr, "Forming and outputting automata tables...");
9523 output_tables ();
9524 if (progress_flag)
9526 fprintf (stderr, "done\n");
9527 fprintf (stderr, "Output functions to work with automata...");
9529 output_chip_definitions ();
9530 output_max_insn_queue_index_def ();
9531 output_internal_min_issue_delay_func ();
9532 output_internal_trans_func ();
9533 /* Cache of insn dfa codes: */
9534 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9535 fprintf (output_file, "\nstatic int %s;\n\n",
9536 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9537 output_dfa_insn_code_func ();
9538 output_trans_func ();
9539 output_min_issue_delay_func ();
9540 output_internal_dead_lock_func ();
9541 output_dead_lock_func ();
9542 output_size_func ();
9543 output_internal_reset_func ();
9544 output_reset_func ();
9545 output_min_insn_conflict_delay_func ();
9546 output_default_latencies ();
9547 output_internal_insn_latency_func ();
9548 output_insn_latency_func ();
9549 output_internal_maximal_insn_latency_func ();
9550 output_maximal_insn_latency_func ();
9551 output_print_reservation_func ();
9552 /* Output function get_cpu_unit_code. */
9553 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9554 output_get_cpu_unit_code_func ();
9555 output_cpu_unit_reservation_p ();
9556 output_insn_has_dfa_reservation_p ();
9557 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9558 CPU_UNITS_QUERY_MACRO_NAME);
9559 output_dfa_clean_insn_cache_func ();
9560 output_dfa_start_func ();
9561 output_dfa_finish_func ();
9562 if (progress_flag)
9563 fprintf (stderr, "done\n");
9564 if (v_flag)
9566 output_description_file = fopen (output_description_file_name, "w");
9567 if (output_description_file == NULL)
9569 perror (output_description_file_name);
9570 exit (FATAL_EXIT_CODE);
9572 if (progress_flag)
9573 fprintf (stderr, "Output automata description...");
9574 output_description ();
9575 output_automaton_descriptions ();
9576 if (progress_flag)
9577 fprintf (stderr, "done\n");
9578 output_statistics (output_description_file);
9580 if (stats_flag)
9581 output_statistics (stderr);
9582 ticker_off (&output_time);
9583 if (time_flag)
9584 output_time_statistics (stderr);
9585 finish_states ();
9586 finish_arcs ();
9587 finish_automata_lists ();
9588 if (time_flag)
9590 fprintf (stderr, "Summary:\n");
9591 fprintf (stderr, " check time ");
9592 print_active_time (stderr, check_time);
9593 fprintf (stderr, ", generation time ");
9594 print_active_time (stderr, generation_time);
9595 fprintf (stderr, ", all time ");
9596 print_active_time (stderr, all_time);
9597 fprintf (stderr, "\n");
9599 /* Finish all work. */
9600 if (output_description_file != NULL)
9602 fflush (output_description_file);
9603 if (ferror (stdout) != 0)
9604 fatal ("Error in writing DFA description file %s: %s",
9605 output_description_file_name, xstrerror (errno));
9606 fclose (output_description_file);
9608 finish_automaton_decl_table ();
9609 finish_insn_decl_table ();
9610 finish_decl_table ();
9611 obstack_free (&irp, NULL);
9612 if (have_error && output_description_file != NULL)
9613 remove (output_description_file_name);
9617 main (int argc, char **argv)
9619 rtx desc;
9621 progname = "genautomata";
9623 if (!init_rtx_reader_args (argc, argv))
9624 return (FATAL_EXIT_CODE);
9626 initiate_automaton_gen (argc, argv);
9627 while (1)
9629 int lineno;
9630 int insn_code_number;
9632 desc = read_md_rtx (&lineno, &insn_code_number);
9633 if (desc == NULL)
9634 break;
9636 switch (GET_CODE (desc))
9638 case DEFINE_CPU_UNIT:
9639 gen_cpu_unit (desc);
9640 break;
9642 case DEFINE_QUERY_CPU_UNIT:
9643 gen_query_cpu_unit (desc);
9644 break;
9646 case DEFINE_BYPASS:
9647 gen_bypass (desc);
9648 break;
9650 case EXCLUSION_SET:
9651 gen_excl_set (desc);
9652 break;
9654 case PRESENCE_SET:
9655 gen_presence_set (desc);
9656 break;
9658 case FINAL_PRESENCE_SET:
9659 gen_final_presence_set (desc);
9660 break;
9662 case ABSENCE_SET:
9663 gen_absence_set (desc);
9664 break;
9666 case FINAL_ABSENCE_SET:
9667 gen_final_absence_set (desc);
9668 break;
9670 case DEFINE_AUTOMATON:
9671 gen_automaton (desc);
9672 break;
9674 case AUTOMATA_OPTION:
9675 gen_automata_option (desc);
9676 break;
9678 case DEFINE_RESERVATION:
9679 gen_reserv (desc);
9680 break;
9682 case DEFINE_INSN_RESERVATION:
9683 gen_insn_reserv (desc);
9684 break;
9686 default:
9687 break;
9691 if (have_error)
9692 return FATAL_EXIT_CODE;
9694 if (VEC_length (decl_t, decls) > 0)
9696 expand_automata ();
9697 if (!have_error)
9699 puts ("/* Generated automatically by the program `genautomata'\n"
9700 " from the machine description file `md'. */\n\n"
9701 "#include \"config.h\"\n"
9702 "#include \"system.h\"\n"
9703 "#include \"coretypes.h\"\n"
9704 "#include \"tm.h\"\n"
9705 "#include \"rtl.h\"\n"
9706 "#include \"tm_p.h\"\n"
9707 "#include \"insn-config.h\"\n"
9708 "#include \"recog.h\"\n"
9709 "#include \"regs.h\"\n"
9710 "#include \"output.h\"\n"
9711 "#include \"insn-attr.h\"\n"
9712 "#include \"diagnostic-core.h\"\n"
9713 "#include \"flags.h\"\n"
9714 "#include \"function.h\"\n"
9715 "#include \"emit-rtl.h\"\n");
9716 /* FIXME: emit-rtl.h can go away once crtl is in rtl.h. */
9718 write_automata ();
9721 else
9723 puts ("/* Generated automatically by the program `genautomata'\n"
9724 " from the machine description file `md'. */\n\n"
9725 "/* There is no automaton, but ISO C forbids empty\n"
9726 " translation units, so include a header file with some\n"
9727 " declarations, and its pre-requisite header file. */\n"
9728 "#include \"config.h\"\n"
9729 "#include \"system.h\"\n");
9732 fflush (stdout);
9733 return (ferror (stdout) != 0 || have_error
9734 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);