comparison gcc/genautomata.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 77e2b8dfacca
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
1 /* Pipeline hazard description translator.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
3 Free Software Foundation, Inc.
4
5 Written by Vladimir Makarov <vmakarov@redhat.com>
6
7 This file is part of GCC.
8
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.
13
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.
18
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/>. */
22
23 /* References:
24
25 1. Detecting pipeline structural hazards quickly. T. Proebsting,
26 C. Fraser. Proceedings of ACM SIGPLAN-SIGACT Symposium on
27 Principles of Programming Languages, pages 280--286, 1994.
28
29 This article is a good start point to understand usage of finite
30 state automata for pipeline hazard recognizers. But I'd
31 recommend the 2nd article for more deep understanding.
32
33 2. Efficient Instruction Scheduling Using Finite State Automata:
34 V. Bala and N. Rubin, Proceedings of MICRO-28. This is the best
35 article about usage of finite state automata for pipeline hazard
36 recognizers.
37
38 The current implementation is different from the 2nd article in the
39 following:
40
41 1. New operator `|' (alternative) is permitted in functional unit
42 reservation which can be treated deterministically and
43 non-deterministically.
44
45 2. Possibility of usage of nondeterministic automata too.
46
47 3. Possibility to query functional unit reservations for given
48 automaton state.
49
50 4. Several constructions to describe impossible reservations
51 (`exclusion_set', `presence_set', `final_presence_set',
52 `absence_set', and `final_absence_set').
53
54 5. No reverse automata are generated. Trace instruction scheduling
55 requires this. It can be easily added in the future if we
56 really need this.
57
58 6. Union of automaton states are not generated yet. It is planned
59 to be implemented. Such feature is needed to make more accurate
60 interlock insn scheduling to get state describing functional
61 unit reservation in a joint CFG point. */
62
63 /* This file code processes constructions of machine description file
64 which describes automaton used for recognition of processor pipeline
65 hazards by insn scheduler and can be used for other tasks (such as
66 VLIW insn packing.
67
68 The translator functions `gen_cpu_unit', `gen_query_cpu_unit',
69 `gen_bypass', `gen_excl_set', `gen_presence_set',
70 `gen_final_presence_set', `gen_absence_set',
71 `gen_final_absence_set', `gen_automaton', `gen_automata_option',
72 `gen_reserv', `gen_insn_reserv' are called from file
73 `genattrtab.c'. They transform RTL constructions describing
74 automata in .md file into internal representation convenient for
75 further processing.
76
77 The translator major function `expand_automata' processes the
78 description internal representation into finite state automaton.
79 It can be divided on:
80
81 o checking correctness of the automaton pipeline description
82 (major function is `check_all_description').
83
84 o generating automaton (automata) from the description (major
85 function is `make_automaton').
86
87 o optional transformation of nondeterministic finite state
88 automata into deterministic ones if the alternative operator
89 `|' is treated nondeterministically in the description (major
90 function is NDFA_to_DFA).
91
92 o optional minimization of the finite state automata by merging
93 equivalent automaton states (major function is `minimize_DFA').
94
95 o forming tables (some as comb vectors) and attributes
96 representing the automata (functions output_..._table).
97
98 Function `write_automata' outputs the created finite state
99 automaton as different tables and functions which works with the
100 automata to inquire automaton state and to change its state. These
101 function are used by gcc instruction scheduler and may be some
102 other gcc code. */
103
104 #include "bconfig.h"
105 #include "system.h"
106 #include "coretypes.h"
107 #include "tm.h"
108 #include "rtl.h"
109 #include "obstack.h"
110 #include "errors.h"
111 #include "gensupport.h"
112
113 #include <math.h>
114 #include "hashtab.h"
115 #include "vec.h"
116
117 #ifndef CHAR_BIT
118 #define CHAR_BIT 8
119 #endif
120
121 /* Positions in machine description file. Now they are not used. But
122 they could be used in the future for better diagnostic messages. */
123 typedef int pos_t;
124
125 /* The following is element of vector of current (and planned in the
126 future) functional unit reservations. */
127 typedef unsigned HOST_WIDE_INT set_el_t;
128
129 /* Reservations of function units are represented by value of the following
130 type. */
131 typedef set_el_t *reserv_sets_t;
132 typedef const set_el_t *const_reserv_sets_t;
133
134 /* The following structure describes a ticker. */
135 struct ticker
136 {
137 /* The following member value is time of the ticker creation with
138 taking into account time when the ticker is off. Active time of
139 the ticker is current time minus the value. */
140 int modified_creation_time;
141 /* The following member value is time (incremented by one) when the
142 ticker was off. Zero value means that now the ticker is on. */
143 int incremented_off_time;
144 };
145
146 /* The ticker is represented by the following type. */
147 typedef struct ticker ticker_t;
148
149 /* The following type describes elements of output vectors. */
150 typedef HOST_WIDE_INT vect_el_t;
151
152 /* Forward declaration of structures of internal representation of
153 pipeline description based on NDFA. */
154
155 struct unit_decl;
156 struct bypass_decl;
157 struct result_decl;
158 struct automaton_decl;
159 struct unit_pattern_rel_decl;
160 struct reserv_decl;
161 struct insn_reserv_decl;
162 struct decl;
163 struct unit_regexp;
164 struct result_regexp;
165 struct reserv_regexp;
166 struct nothing_regexp;
167 struct sequence_regexp;
168 struct repeat_regexp;
169 struct allof_regexp;
170 struct oneof_regexp;
171 struct regexp;
172 struct description;
173 struct unit_set_el;
174 struct pattern_set_el;
175 struct pattern_reserv;
176 struct state;
177 struct alt_state;
178 struct arc;
179 struct ainsn;
180 struct automaton;
181 struct state_ainsn_table;
182
183 /* The following typedefs are for brevity. */
184 typedef struct unit_decl *unit_decl_t;
185 typedef const struct unit_decl *const_unit_decl_t;
186 typedef struct decl *decl_t;
187 typedef const struct decl *const_decl_t;
188 typedef struct regexp *regexp_t;
189 typedef struct unit_set_el *unit_set_el_t;
190 typedef struct pattern_set_el *pattern_set_el_t;
191 typedef struct pattern_reserv *pattern_reserv_t;
192 typedef struct alt_state *alt_state_t;
193 typedef struct state *state_t;
194 typedef const struct state *const_state_t;
195 typedef struct arc *arc_t;
196 typedef struct ainsn *ainsn_t;
197 typedef struct automaton *automaton_t;
198 typedef struct automata_list_el *automata_list_el_t;
199 typedef const struct automata_list_el *const_automata_list_el_t;
200 typedef struct state_ainsn_table *state_ainsn_table_t;
201
202 /* Undefined position. */
203 static pos_t no_pos = 0;
204
205 /* All IR is stored in the following obstack. */
206 static struct obstack irp;
207
208
209 /* Declare vector types for various data structures: */
210
211 DEF_VEC_P(alt_state_t);
212 DEF_VEC_ALLOC_P(alt_state_t,heap);
213 DEF_VEC_P(ainsn_t);
214 DEF_VEC_ALLOC_P(ainsn_t,heap);
215 DEF_VEC_P(state_t);
216 DEF_VEC_ALLOC_P(state_t,heap);
217 DEF_VEC_P(decl_t);
218 DEF_VEC_ALLOC_P(decl_t,heap);
219 DEF_VEC_P(reserv_sets_t);
220 DEF_VEC_ALLOC_P(reserv_sets_t,heap);
221
222 DEF_VEC_I(vect_el_t);
223 DEF_VEC_ALLOC_I(vect_el_t, heap);
224 typedef VEC(vect_el_t,heap) *vla_hwint_t;
225
226 /* Forward declarations of functions used before their definitions, only. */
227 static regexp_t gen_regexp_sequence (const char *);
228 static void reserv_sets_or (reserv_sets_t, reserv_sets_t,
229 reserv_sets_t);
230 static reserv_sets_t get_excl_set (reserv_sets_t);
231 static int check_presence_pattern_sets (reserv_sets_t,
232 reserv_sets_t, int);
233 static int check_absence_pattern_sets (reserv_sets_t, reserv_sets_t,
234 int);
235 static arc_t first_out_arc (const_state_t);
236 static arc_t next_out_arc (arc_t);
237
238
239
240 /* Options with the following names can be set up in automata_option
241 construction. Because the strings occur more one time we use the
242 macros. */
243
244 #define NO_MINIMIZATION_OPTION "-no-minimization"
245 #define TIME_OPTION "-time"
246 #define STATS_OPTION "-stats"
247 #define V_OPTION "-v"
248 #define W_OPTION "-w"
249 #define NDFA_OPTION "-ndfa"
250 #define PROGRESS_OPTION "-progress"
251
252 /* The following flags are set up by function `initiate_automaton_gen'. */
253
254 /* Make automata with nondeterministic reservation by insns (`-ndfa'). */
255 static int ndfa_flag;
256
257 /* Do not make minimization of DFA (`-no-minimization'). */
258 static int no_minimization_flag;
259
260 /* Value of this variable is number of automata being generated. The
261 actual number of automata may be less this value if there is not
262 sufficient number of units. This value is defined by argument of
263 option `-split' or by constructions automaton if the value is zero
264 (it is default value of the argument). */
265 static int split_argument;
266
267 /* Flag of output time statistics (`-time'). */
268 static int time_flag;
269
270 /* Flag of automata statistics (`-stats'). */
271 static int stats_flag;
272
273 /* Flag of creation of description file which contains description of
274 result automaton and statistics information (`-v'). */
275 static int v_flag;
276
277 /* Flag of output of a progress bar showing how many states were
278 generated so far for automaton being processed (`-progress'). */
279 static int progress_flag;
280
281 /* Flag of generating warning instead of error for non-critical errors
282 (`-w'). */
283 static int w_flag;
284
285
286 /* Output file for pipeline hazard recognizer (PHR) being generated.
287 The value is NULL if the file is not defined. */
288 static FILE *output_file;
289
290 /* Description file of PHR. The value is NULL if the file is not
291 created. */
292 static FILE *output_description_file;
293
294 /* PHR description file name. */
295 static char *output_description_file_name;
296
297 /* Value of the following variable is node representing description
298 being processed. This is start point of IR. */
299 static struct description *description;
300
301
302
303 /* This page contains description of IR structure (nodes). */
304
305 enum decl_mode
306 {
307 dm_unit,
308 dm_bypass,
309 dm_automaton,
310 dm_excl,
311 dm_presence,
312 dm_absence,
313 dm_reserv,
314 dm_insn_reserv
315 };
316
317 /* This describes define_cpu_unit and define_query_cpu_unit (see file
318 rtl.def). */
319 struct unit_decl
320 {
321 const char *name;
322 /* NULL if the automaton name is absent. */
323 const char *automaton_name;
324 /* If the following value is not zero, the cpu unit reservation is
325 described in define_query_cpu_unit. */
326 char query_p;
327
328 /* The following fields are defined by checker. */
329
330 /* The following field value is nonzero if the unit is used in an
331 regexp. */
332 char unit_is_used;
333
334 /* The following field value is order number (0, 1, ...) of given
335 unit. */
336 int unit_num;
337 /* The following field value is corresponding declaration of
338 automaton which was given in description. If the field value is
339 NULL then automaton in the unit declaration was absent. */
340 struct automaton_decl *automaton_decl;
341 /* The following field value is maximal cycle number (1, ...) on
342 which given unit occurs in insns. Zero value means that given
343 unit is not used in insns. */
344 int max_occ_cycle_num;
345 /* The following field value is minimal cycle number (0, ...) on
346 which given unit occurs in insns. -1 value means that given
347 unit is not used in insns. */
348 int min_occ_cycle_num;
349 /* The following list contains units which conflict with given
350 unit. */
351 unit_set_el_t excl_list;
352 /* The following list contains patterns which are required to
353 reservation of given unit. */
354 pattern_set_el_t presence_list;
355 pattern_set_el_t final_presence_list;
356 /* The following list contains patterns which should be not present
357 in reservation for given unit. */
358 pattern_set_el_t absence_list;
359 pattern_set_el_t final_absence_list;
360 /* The following is used only when `query_p' has nonzero value.
361 This is query number for the unit. */
362 int query_num;
363 /* The following is the last cycle on which the unit was checked for
364 correct distributions of units to automata in a regexp. */
365 int last_distribution_check_cycle;
366
367 /* The following fields are defined by automaton generator. */
368
369 /* The following field value is number of the automaton to which
370 given unit belongs. */
371 int corresponding_automaton_num;
372 /* If the following value is not zero, the cpu unit is present in a
373 `exclusion_set' or in right part of a `presence_set',
374 `final_presence_set', `absence_set', and
375 `final_absence_set'define_query_cpu_unit. */
376 char in_set_p;
377 };
378
379 /* This describes define_bypass (see file rtl.def). */
380 struct bypass_decl
381 {
382 int latency;
383 const char *out_insn_name;
384 const char *in_insn_name;
385 const char *bypass_guard_name;
386
387 /* The following fields are defined by checker. */
388
389 /* output and input insns of given bypass. */
390 struct insn_reserv_decl *out_insn_reserv;
391 struct insn_reserv_decl *in_insn_reserv;
392 /* The next bypass for given output insn. */
393 struct bypass_decl *next;
394 };
395
396 /* This describes define_automaton (see file rtl.def). */
397 struct automaton_decl
398 {
399 const char *name;
400
401 /* The following fields are defined by automaton generator. */
402
403 /* The following field value is nonzero if the automaton is used in
404 an regexp definition. */
405 char automaton_is_used;
406
407 /* The following fields are defined by checker. */
408
409 /* The following field value is the corresponding automaton. This
410 field is not NULL only if the automaton is present in unit
411 declarations and the automatic partition on automata is not
412 used. */
413 automaton_t corresponding_automaton;
414 };
415
416 /* This describes exclusion relations: exclusion_set (see file
417 rtl.def). */
418 struct excl_rel_decl
419 {
420 int all_names_num;
421 int first_list_length;
422 char *names [1];
423 };
424
425 /* This describes unit relations: [final_]presence_set or
426 [final_]absence_set (see file rtl.def). */
427 struct unit_pattern_rel_decl
428 {
429 int final_p;
430 int names_num;
431 int patterns_num;
432 char **names;
433 char ***patterns;
434 };
435
436 /* This describes define_reservation (see file rtl.def). */
437 struct reserv_decl
438 {
439 const char *name;
440 regexp_t regexp;
441
442 /* The following fields are defined by checker. */
443
444 /* The following field value is nonzero if the unit is used in an
445 regexp. */
446 char reserv_is_used;
447 /* The following field is used to check up cycle in expression
448 definition. */
449 int loop_pass_num;
450 };
451
452 /* This describes define_insn_reservation (see file rtl.def). */
453 struct insn_reserv_decl
454 {
455 rtx condexp;
456 int default_latency;
457 regexp_t regexp;
458 const char *name;
459
460 /* The following fields are defined by checker. */
461
462 /* The following field value is order number (0, 1, ...) of given
463 insn. */
464 int insn_num;
465 /* The following field value is list of bypasses in which given insn
466 is output insn. */
467 struct bypass_decl *bypass_list;
468
469 /* The following fields are defined by automaton generator. */
470
471 /* The following field is the insn regexp transformed that
472 the regexp has not optional regexp, repetition regexp, and an
473 reservation name (i.e. reservation identifiers are changed by the
474 corresponding regexp) and all alternations are the top level
475 of the regexp. The value can be NULL only if it is special
476 insn `cycle advancing'. */
477 regexp_t transformed_regexp;
478 /* The following field value is list of arcs marked given
479 insn. The field is used in transformation NDFA -> DFA. */
480 arc_t arcs_marked_by_insn;
481 /* The two following fields are used during minimization of a finite state
482 automaton. */
483 /* The field value is number of equivalence class of state into
484 which arc marked by given insn enters from a state (fixed during
485 an automaton minimization). */
486 int equiv_class_num;
487 /* The following member value is the list to automata which can be
488 changed by the insn issue. */
489 automata_list_el_t important_automata_list;
490 /* The following member is used to process insn once for output. */
491 int processed_p;
492 };
493
494 /* This contains a declaration mentioned above. */
495 struct decl
496 {
497 /* What node in the union? */
498 enum decl_mode mode;
499 pos_t pos;
500 union
501 {
502 struct unit_decl unit;
503 struct bypass_decl bypass;
504 struct automaton_decl automaton;
505 struct excl_rel_decl excl;
506 struct unit_pattern_rel_decl presence;
507 struct unit_pattern_rel_decl absence;
508 struct reserv_decl reserv;
509 struct insn_reserv_decl insn_reserv;
510 } decl;
511 };
512
513 /* The following structures represent parsed reservation strings. */
514 enum regexp_mode
515 {
516 rm_unit,
517 rm_reserv,
518 rm_nothing,
519 rm_sequence,
520 rm_repeat,
521 rm_allof,
522 rm_oneof
523 };
524
525 /* Cpu unit in reservation. */
526 struct unit_regexp
527 {
528 const char *name;
529 unit_decl_t unit_decl;
530 };
531
532 /* Define_reservation in a reservation. */
533 struct reserv_regexp
534 {
535 const char *name;
536 struct reserv_decl *reserv_decl;
537 };
538
539 /* Absence of reservation (represented by string `nothing'). */
540 struct nothing_regexp
541 {
542 /* This used to be empty but ISO C doesn't allow that. */
543 char unused;
544 };
545
546 /* Representation of reservations separated by ',' (see file
547 rtl.def). */
548 struct sequence_regexp
549 {
550 int regexps_num;
551 regexp_t regexps [1];
552 };
553
554 /* Representation of construction `repeat' (see file rtl.def). */
555 struct repeat_regexp
556 {
557 int repeat_num;
558 regexp_t regexp;
559 };
560
561 /* Representation of reservations separated by '+' (see file
562 rtl.def). */
563 struct allof_regexp
564 {
565 int regexps_num;
566 regexp_t regexps [1];
567 };
568
569 /* Representation of reservations separated by '|' (see file
570 rtl.def). */
571 struct oneof_regexp
572 {
573 int regexps_num;
574 regexp_t regexps [1];
575 };
576
577 /* Representation of a reservation string. */
578 struct regexp
579 {
580 /* What node in the union? */
581 enum regexp_mode mode;
582 pos_t pos;
583 union
584 {
585 struct unit_regexp unit;
586 struct reserv_regexp reserv;
587 struct nothing_regexp nothing;
588 struct sequence_regexp sequence;
589 struct repeat_regexp repeat;
590 struct allof_regexp allof;
591 struct oneof_regexp oneof;
592 } regexp;
593 };
594
595 /* Represents description of pipeline hazard description based on
596 NDFA. */
597 struct description
598 {
599 int decls_num;
600
601 /* The following fields are defined by checker. */
602
603 /* The following fields values are correspondingly number of all
604 units, query units, and insns in the description. */
605 int units_num;
606 int query_units_num;
607 int insns_num;
608 /* The following field value is max length (in cycles) of
609 reservations of insns. The field value is defined only for
610 correct programs. */
611 int max_insn_reserv_cycles;
612
613 /* The following fields are defined by automaton generator. */
614
615 /* The following field value is the first automaton. */
616 automaton_t first_automaton;
617
618 /* The following field is created by pipeline hazard parser and
619 contains all declarations. We allocate additional entry for
620 special insn "cycle advancing" which is added by the automaton
621 generator. */
622 decl_t decls [1];
623 };
624
625
626 /* The following nodes are created in automaton checker. */
627
628 /* The following nodes represent exclusion set for cpu units. Each
629 element is accessed through only one excl_list. */
630 struct unit_set_el
631 {
632 unit_decl_t unit_decl;
633 unit_set_el_t next_unit_set_el;
634 };
635
636 /* The following nodes represent presence or absence pattern for cpu
637 units. Each element is accessed through only one presence_list or
638 absence_list. */
639 struct pattern_set_el
640 {
641 /* The number of units in unit_decls. */
642 int units_num;
643 /* The units forming the pattern. */
644 struct unit_decl **unit_decls;
645 pattern_set_el_t next_pattern_set_el;
646 };
647
648
649 /* The following nodes are created in automaton generator. */
650
651
652 /* The following nodes represent presence or absence pattern for cpu
653 units. Each element is accessed through only one element of
654 unit_presence_set_table or unit_absence_set_table. */
655 struct pattern_reserv
656 {
657 reserv_sets_t reserv;
658 pattern_reserv_t next_pattern_reserv;
659 };
660
661 /* The following node type describes state automaton. The state may
662 be deterministic or non-deterministic. Non-deterministic state has
663 several component states which represent alternative cpu units
664 reservations. The state also is used for describing a
665 deterministic reservation of automaton insn. */
666 struct state
667 {
668 /* The following member value is nonzero if there is a transition by
669 cycle advancing. */
670 int new_cycle_p;
671 /* The following field is list of processor unit reservations on
672 each cycle. */
673 reserv_sets_t reservs;
674 /* The following field is unique number of given state between other
675 states. */
676 int unique_num;
677 /* The following field value is automaton to which given state
678 belongs. */
679 automaton_t automaton;
680 /* The following field value is the first arc output from given
681 state. */
682 arc_t first_out_arc;
683 unsigned int num_out_arcs;
684 /* The following field is used to form NDFA. */
685 char it_was_placed_in_stack_for_NDFA_forming;
686 /* The following field is used to form DFA. */
687 char it_was_placed_in_stack_for_DFA_forming;
688 /* The following field is used to transform NDFA to DFA and DFA
689 minimization. The field value is not NULL if the state is a
690 compound state. In this case the value of field `unit_sets_list'
691 is NULL. All states in the list are in the hash table. The list
692 is formed through field `next_sorted_alt_state'. We should
693 support only one level of nesting state. */
694 alt_state_t component_states;
695 /* The following field is used for passing graph of states. */
696 int pass_num;
697 /* The list of states belonging to one equivalence class is formed
698 with the aid of the following field. */
699 state_t next_equiv_class_state;
700 /* The two following fields are used during minimization of a finite
701 state automaton. */
702 int equiv_class_num_1, equiv_class_num_2;
703 /* The following field is used during minimization of a finite state
704 automaton. The field value is state corresponding to equivalence
705 class to which given state belongs. */
706 state_t equiv_class_state;
707 unsigned int *presence_signature;
708 /* The following field value is the order number of given state.
709 The states in final DFA is enumerated with the aid of the
710 following field. */
711 int order_state_num;
712 /* This member is used for passing states for searching minimal
713 delay time. */
714 int state_pass_num;
715 /* The following member is used to evaluate min issue delay of insn
716 for a state. */
717 int min_insn_issue_delay;
718 };
719
720 /* Automaton arc. */
721 struct arc
722 {
723 /* The following field refers for the state into which given arc
724 enters. */
725 state_t to_state;
726 /* The following field describes that the insn issue (with cycle
727 advancing for special insn `cycle advancing' and without cycle
728 advancing for others) makes transition from given state to
729 another given state. */
730 ainsn_t insn;
731 /* The following field value is the next arc output from the same
732 state. */
733 arc_t next_out_arc;
734 /* List of arcs marked given insn is formed with the following
735 field. The field is used in transformation NDFA -> DFA. */
736 arc_t next_arc_marked_by_insn;
737 };
738
739 /* The following node type describes a deterministic alternative in
740 non-deterministic state which characterizes cpu unit reservations
741 of automaton insn or which is part of NDFA. */
742 struct alt_state
743 {
744 /* The following field is a deterministic state which characterizes
745 unit reservations of the instruction. */
746 state_t state;
747 /* The following field refers to the next state which characterizes
748 unit reservations of the instruction. */
749 alt_state_t next_alt_state;
750 /* The following field refers to the next state in sorted list. */
751 alt_state_t next_sorted_alt_state;
752 };
753
754 /* The following node type describes insn of automaton. They are
755 labels of FA arcs. */
756 struct ainsn
757 {
758 /* The following field value is the corresponding insn declaration
759 of description. */
760 struct insn_reserv_decl *insn_reserv_decl;
761 /* The following field value is the next insn declaration for an
762 automaton. */
763 ainsn_t next_ainsn;
764 /* The following field is states which characterize automaton unit
765 reservations of the instruction. The value can be NULL only if it
766 is special insn `cycle advancing'. */
767 alt_state_t alt_states;
768 /* The following field is sorted list of states which characterize
769 automaton unit reservations of the instruction. The value can be
770 NULL only if it is special insn `cycle advancing'. */
771 alt_state_t sorted_alt_states;
772 /* The following field refers the next automaton insn with
773 the same reservations. */
774 ainsn_t next_same_reservs_insn;
775 /* The following field is flag of the first automaton insn with the
776 same reservations in the declaration list. Only arcs marked such
777 insn is present in the automaton. This significantly decreases
778 memory requirements especially when several automata are
779 formed. */
780 char first_insn_with_same_reservs;
781 /* The following member has nonzero value if there is arc from state of
782 the automaton marked by the ainsn. */
783 char arc_exists_p;
784 /* Cyclic list of insns of an equivalence class is formed with the
785 aid of the following field. */
786 ainsn_t next_equiv_class_insn;
787 /* The following field value is nonzero if the insn declaration is
788 the first insn declaration with given equivalence number. */
789 char first_ainsn_with_given_equivalence_num;
790 /* The following field is number of class of equivalence of insns.
791 It is necessary because many insns may be equivalent with the
792 point of view of pipeline hazards. */
793 int insn_equiv_class_num;
794 /* The following member value is TRUE if there is an arc in the
795 automaton marked by the insn into another state. In other
796 words, the insn can change the state of the automaton. */
797 int important_p;
798 };
799
800 /* The following describes an automaton for PHR. */
801 struct automaton
802 {
803 /* The following field value is the list of insn declarations for
804 given automaton. */
805 ainsn_t ainsn_list;
806 /* The following field value is the corresponding automaton
807 declaration. This field is not NULL only if the automatic
808 partition on automata is not used. */
809 struct automaton_decl *corresponding_automaton_decl;
810 /* The following field value is the next automaton. */
811 automaton_t next_automaton;
812 /* The following field is start state of FA. There are not unit
813 reservations in the state. */
814 state_t start_state;
815 /* The following field value is number of equivalence classes of
816 insns (see field `insn_equiv_class_num' in
817 `insn_reserv_decl'). */
818 int insn_equiv_classes_num;
819 /* The following field value is number of states of final DFA. */
820 int achieved_states_num;
821 /* The following field value is the order number (0, 1, ...) of
822 given automaton. */
823 int automaton_order_num;
824 /* The following fields contain statistics information about
825 building automaton. */
826 int NDFA_states_num, DFA_states_num;
827 /* The following field value is defined only if minimization of DFA
828 is used. */
829 int minimal_DFA_states_num;
830 int NDFA_arcs_num, DFA_arcs_num;
831 /* The following field value is defined only if minimization of DFA
832 is used. */
833 int minimal_DFA_arcs_num;
834 /* The following member refers for two table state x ainsn -> int.
835 ??? Above sentence is incomprehensible. */
836 state_ainsn_table_t trans_table;
837 /* The following member value is maximal value of min issue delay
838 for insns of the automaton. */
839 int max_min_delay;
840 /* Usually min issue delay is small and we can place several (2, 4,
841 8) elements in one vector element. So the compression factor can
842 be 1 (no compression), 2, 4, 8. */
843 int min_issue_delay_table_compression_factor;
844 /* Total number of locked states in this automaton. */
845 int locked_states;
846 };
847
848 /* The following is the element of the list of automata. */
849 struct automata_list_el
850 {
851 /* The automaton itself. */
852 automaton_t automaton;
853 /* The next automata set element. */
854 automata_list_el_t next_automata_list_el;
855 };
856
857 /* The following structure describes a table state X ainsn -> int(>= 0). */
858 struct state_ainsn_table
859 {
860 /* Automaton to which given table belongs. */
861 automaton_t automaton;
862 /* The following tree vectors for comb vector implementation of the
863 table. */
864 vla_hwint_t comb_vect;
865 vla_hwint_t check_vect;
866 vla_hwint_t base_vect;
867 /* This is simple implementation of the table. */
868 vla_hwint_t full_vect;
869 /* Minimal and maximal values of the previous vectors. */
870 int min_comb_vect_el_value, max_comb_vect_el_value;
871 int min_base_vect_el_value, max_base_vect_el_value;
872 };
873
874 /* Macros to access members of unions. Use only them for access to
875 union members of declarations and regexps. */
876
877 #if defined ENABLE_CHECKING && (GCC_VERSION >= 2007)
878
879 #define DECL_UNIT(d) __extension__ \
880 (({ __typeof (d) const _decl = (d); \
881 if (_decl->mode != dm_unit) \
882 decl_mode_check_failed (_decl->mode, "dm_unit", \
883 __FILE__, __LINE__, __FUNCTION__); \
884 &(_decl)->decl.unit; }))
885
886 #define DECL_BYPASS(d) __extension__ \
887 (({ __typeof (d) const _decl = (d); \
888 if (_decl->mode != dm_bypass) \
889 decl_mode_check_failed (_decl->mode, "dm_bypass", \
890 __FILE__, __LINE__, __FUNCTION__); \
891 &(_decl)->decl.bypass; }))
892
893 #define DECL_AUTOMATON(d) __extension__ \
894 (({ __typeof (d) const _decl = (d); \
895 if (_decl->mode != dm_automaton) \
896 decl_mode_check_failed (_decl->mode, "dm_automaton", \
897 __FILE__, __LINE__, __FUNCTION__); \
898 &(_decl)->decl.automaton; }))
899
900 #define DECL_EXCL(d) __extension__ \
901 (({ __typeof (d) const _decl = (d); \
902 if (_decl->mode != dm_excl) \
903 decl_mode_check_failed (_decl->mode, "dm_excl", \
904 __FILE__, __LINE__, __FUNCTION__); \
905 &(_decl)->decl.excl; }))
906
907 #define DECL_PRESENCE(d) __extension__ \
908 (({ __typeof (d) const _decl = (d); \
909 if (_decl->mode != dm_presence) \
910 decl_mode_check_failed (_decl->mode, "dm_presence", \
911 __FILE__, __LINE__, __FUNCTION__); \
912 &(_decl)->decl.presence; }))
913
914 #define DECL_ABSENCE(d) __extension__ \
915 (({ __typeof (d) const _decl = (d); \
916 if (_decl->mode != dm_absence) \
917 decl_mode_check_failed (_decl->mode, "dm_absence", \
918 __FILE__, __LINE__, __FUNCTION__); \
919 &(_decl)->decl.absence; }))
920
921 #define DECL_RESERV(d) __extension__ \
922 (({ __typeof (d) const _decl = (d); \
923 if (_decl->mode != dm_reserv) \
924 decl_mode_check_failed (_decl->mode, "dm_reserv", \
925 __FILE__, __LINE__, __FUNCTION__); \
926 &(_decl)->decl.reserv; }))
927
928 #define DECL_INSN_RESERV(d) __extension__ \
929 (({ __typeof (d) const _decl = (d); \
930 if (_decl->mode != dm_insn_reserv) \
931 decl_mode_check_failed (_decl->mode, "dm_insn_reserv", \
932 __FILE__, __LINE__, __FUNCTION__); \
933 &(_decl)->decl.insn_reserv; }))
934
935 static const char *decl_name (enum decl_mode);
936 static void decl_mode_check_failed (enum decl_mode, const char *,
937 const char *, int, const char *)
938 ATTRIBUTE_NORETURN;
939
940 /* Return string representation of declaration mode MODE. */
941 static const char *
942 decl_name (enum decl_mode mode)
943 {
944 static char str [100];
945
946 if (mode == dm_unit)
947 return "dm_unit";
948 else if (mode == dm_bypass)
949 return "dm_bypass";
950 else if (mode == dm_automaton)
951 return "dm_automaton";
952 else if (mode == dm_excl)
953 return "dm_excl";
954 else if (mode == dm_presence)
955 return "dm_presence";
956 else if (mode == dm_absence)
957 return "dm_absence";
958 else if (mode == dm_reserv)
959 return "dm_reserv";
960 else if (mode == dm_insn_reserv)
961 return "dm_insn_reserv";
962 else
963 sprintf (str, "unknown (%d)", (int) mode);
964 return str;
965 }
966
967 /* The function prints message about unexpected declaration and finish
968 the program. */
969 static void
970 decl_mode_check_failed (enum decl_mode mode, const char *expected_mode_str,
971 const char *file, int line, const char *func)
972 {
973 fprintf
974 (stderr,
975 "\n%s: %d: error in %s: DECL check: expected decl %s, have %s\n",
976 file, line, func, expected_mode_str, decl_name (mode));
977 exit (1);
978 }
979
980
981 #define REGEXP_UNIT(r) __extension__ \
982 (({ struct regexp *const _regexp = (r); \
983 if (_regexp->mode != rm_unit) \
984 regexp_mode_check_failed (_regexp->mode, "rm_unit", \
985 __FILE__, __LINE__, __FUNCTION__); \
986 &(_regexp)->regexp.unit; }))
987
988 #define REGEXP_RESERV(r) __extension__ \
989 (({ struct regexp *const _regexp = (r); \
990 if (_regexp->mode != rm_reserv) \
991 regexp_mode_check_failed (_regexp->mode, "rm_reserv", \
992 __FILE__, __LINE__, __FUNCTION__); \
993 &(_regexp)->regexp.reserv; }))
994
995 #define REGEXP_SEQUENCE(r) __extension__ \
996 (({ struct regexp *const _regexp = (r); \
997 if (_regexp->mode != rm_sequence) \
998 regexp_mode_check_failed (_regexp->mode, "rm_sequence", \
999 __FILE__, __LINE__, __FUNCTION__); \
1000 &(_regexp)->regexp.sequence; }))
1001
1002 #define REGEXP_REPEAT(r) __extension__ \
1003 (({ struct regexp *const _regexp = (r); \
1004 if (_regexp->mode != rm_repeat) \
1005 regexp_mode_check_failed (_regexp->mode, "rm_repeat", \
1006 __FILE__, __LINE__, __FUNCTION__); \
1007 &(_regexp)->regexp.repeat; }))
1008
1009 #define REGEXP_ALLOF(r) __extension__ \
1010 (({ struct regexp *const _regexp = (r); \
1011 if (_regexp->mode != rm_allof) \
1012 regexp_mode_check_failed (_regexp->mode, "rm_allof", \
1013 __FILE__, __LINE__, __FUNCTION__); \
1014 &(_regexp)->regexp.allof; }))
1015
1016 #define REGEXP_ONEOF(r) __extension__ \
1017 (({ struct regexp *const _regexp = (r); \
1018 if (_regexp->mode != rm_oneof) \
1019 regexp_mode_check_failed (_regexp->mode, "rm_oneof", \
1020 __FILE__, __LINE__, __FUNCTION__); \
1021 &(_regexp)->regexp.oneof; }))
1022
1023 static const char *regexp_name (enum regexp_mode);
1024 static void regexp_mode_check_failed (enum regexp_mode, const char *,
1025 const char *, int,
1026 const char *) ATTRIBUTE_NORETURN;
1027
1028
1029 /* Return string representation of regexp mode MODE. */
1030 static const char *
1031 regexp_name (enum regexp_mode mode)
1032 {
1033 switch (mode)
1034 {
1035 case rm_unit:
1036 return "rm_unit";
1037 case rm_reserv:
1038 return "rm_reserv";
1039 case rm_nothing:
1040 return "rm_nothing";
1041 case rm_sequence:
1042 return "rm_sequence";
1043 case rm_repeat:
1044 return "rm_repeat";
1045 case rm_allof:
1046 return "rm_allof";
1047 case rm_oneof:
1048 return "rm_oneof";
1049 default:
1050 gcc_unreachable ();
1051 }
1052 }
1053
1054 /* The function prints message about unexpected regexp and finish the
1055 program. */
1056 static void
1057 regexp_mode_check_failed (enum regexp_mode mode,
1058 const char *expected_mode_str,
1059 const char *file, int line, const char *func)
1060 {
1061 fprintf
1062 (stderr,
1063 "\n%s: %d: error in %s: REGEXP check: expected decl %s, have %s\n",
1064 file, line, func, expected_mode_str, regexp_name (mode));
1065 exit (1);
1066 }
1067
1068 #else /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1069
1070 #define DECL_UNIT(d) (&(d)->decl.unit)
1071 #define DECL_BYPASS(d) (&(d)->decl.bypass)
1072 #define DECL_AUTOMATON(d) (&(d)->decl.automaton)
1073 #define DECL_EXCL(d) (&(d)->decl.excl)
1074 #define DECL_PRESENCE(d) (&(d)->decl.presence)
1075 #define DECL_ABSENCE(d) (&(d)->decl.absence)
1076 #define DECL_RESERV(d) (&(d)->decl.reserv)
1077 #define DECL_INSN_RESERV(d) (&(d)->decl.insn_reserv)
1078
1079 #define REGEXP_UNIT(r) (&(r)->regexp.unit)
1080 #define REGEXP_RESERV(r) (&(r)->regexp.reserv)
1081 #define REGEXP_SEQUENCE(r) (&(r)->regexp.sequence)
1082 #define REGEXP_REPEAT(r) (&(r)->regexp.repeat)
1083 #define REGEXP_ALLOF(r) (&(r)->regexp.allof)
1084 #define REGEXP_ONEOF(r) (&(r)->regexp.oneof)
1085
1086 #endif /* #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) */
1087
1088 #define XCREATENODE(T) ((T *) create_node (sizeof (T)))
1089 #define XCREATENODEVEC(T, N) ((T *) create_node (sizeof (T) * (N)))
1090 #define XCREATENODEVAR(T, S) ((T *) create_node ((S)))
1091
1092 #define XCOPYNODE(T, P) ((T *) copy_node ((P), sizeof (T)))
1093 #define XCOPYNODEVEC(T, P, N) ((T *) copy_node ((P), sizeof (T) * (N)))
1094 #define XCOPYNODEVAR(T, P, S) ((T *) copy_node ((P), (S)))
1095
1096 /* Create IR structure (node). */
1097 static void *
1098 create_node (size_t size)
1099 {
1100 void *result;
1101
1102 obstack_blank (&irp, size);
1103 result = obstack_base (&irp);
1104 obstack_finish (&irp);
1105 /* Default values of members are NULL and zero. */
1106 memset (result, 0, size);
1107 return result;
1108 }
1109
1110 /* Copy IR structure (node). */
1111 static void *
1112 copy_node (const void *from, size_t size)
1113 {
1114 void *const result = create_node (size);
1115 memcpy (result, from, size);
1116 return result;
1117 }
1118
1119 /* The function checks that NAME does not contain quotes (`"'). */
1120 static const char *
1121 check_name (const char * name, pos_t pos ATTRIBUTE_UNUSED)
1122 {
1123 const char *str;
1124
1125 for (str = name; *str != '\0'; str++)
1126 if (*str == '\"')
1127 error ("Name `%s' contains quotes", name);
1128 return name;
1129 }
1130
1131 /* Pointers to all declarations during IR generation are stored in the
1132 following. */
1133 static VEC(decl_t,heap) *decls;
1134
1135 /* Given a pointer to a (char *) and a separator, return an alloc'ed
1136 string containing the next separated element, taking parentheses
1137 into account if PAR_FLAG has nonzero value. Advance the pointer to
1138 after the string scanned, or the end-of-string. Return NULL if at
1139 end of string. */
1140 static char *
1141 next_sep_el (const char **pstr, int sep, int par_flag)
1142 {
1143 char *out_str;
1144 const char *p;
1145 int pars_num;
1146 int n_spaces;
1147
1148 /* Remove leading whitespaces. */
1149 while (ISSPACE ((int) **pstr))
1150 (*pstr)++;
1151
1152 if (**pstr == '\0')
1153 return NULL;
1154
1155 n_spaces = 0;
1156 for (pars_num = 0, p = *pstr; *p != '\0'; p++)
1157 {
1158 if (par_flag && *p == '(')
1159 pars_num++;
1160 else if (par_flag && *p == ')')
1161 pars_num--;
1162 else if (pars_num == 0 && *p == sep)
1163 break;
1164 if (pars_num == 0 && ISSPACE ((int) *p))
1165 n_spaces++;
1166 else
1167 {
1168 for (; n_spaces != 0; n_spaces--)
1169 obstack_1grow (&irp, p [-n_spaces]);
1170 obstack_1grow (&irp, *p);
1171 }
1172 }
1173 obstack_1grow (&irp, '\0');
1174 out_str = obstack_base (&irp);
1175 obstack_finish (&irp);
1176
1177 *pstr = p;
1178 if (**pstr == sep)
1179 (*pstr)++;
1180
1181 return out_str;
1182 }
1183
1184 /* Given a string and a separator, return the number of separated
1185 elements in it, taking parentheses into account if PAR_FLAG has
1186 nonzero value. Return 0 for the null string, -1 if parentheses is
1187 not balanced. */
1188 static int
1189 n_sep_els (const char *s, int sep, int par_flag)
1190 {
1191 int n;
1192 int pars_num;
1193
1194 if (*s == '\0')
1195 return 0;
1196
1197 for (pars_num = 0, n = 1; *s; s++)
1198 if (par_flag && *s == '(')
1199 pars_num++;
1200 else if (par_flag && *s == ')')
1201 pars_num--;
1202 else if (pars_num == 0 && *s == sep)
1203 n++;
1204
1205 return (pars_num != 0 ? -1 : n);
1206 }
1207
1208 /* Given a string and a separator, return vector of strings which are
1209 elements in the string and number of elements through els_num.
1210 Take parentheses into account if PAREN_P has nonzero value. The
1211 function also inserts the end marker NULL at the end of vector.
1212 Return 0 for the null string, -1 if parentheses are not balanced. */
1213 static char **
1214 get_str_vect (const char *str, int *els_num, int sep, int paren_p)
1215 {
1216 int i;
1217 char **vect;
1218 const char **pstr;
1219 char *trail;
1220
1221 *els_num = n_sep_els (str, sep, paren_p);
1222 if (*els_num <= 0)
1223 return NULL;
1224 obstack_blank (&irp, sizeof (char *) * (*els_num + 1));
1225 vect = (char **) obstack_base (&irp);
1226 obstack_finish (&irp);
1227 pstr = &str;
1228 for (i = 0; i < *els_num; i++)
1229 vect [i] = next_sep_el (pstr, sep, paren_p);
1230 trail = next_sep_el (pstr, sep, paren_p);
1231 gcc_assert (!trail);
1232 vect [i] = NULL;
1233 return vect;
1234 }
1235
1236 /* Process a DEFINE_CPU_UNIT.
1237
1238 This gives information about a unit contained in CPU. We fill a
1239 struct unit_decl with information used later by `expand_automata'. */
1240 static void
1241 gen_cpu_unit (rtx def)
1242 {
1243 decl_t decl;
1244 char **str_cpu_units;
1245 int vect_length;
1246 int i;
1247
1248 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1249 if (str_cpu_units == NULL)
1250 fatal ("invalid string `%s' in define_cpu_unit", XSTR (def, 0));
1251 for (i = 0; i < vect_length; i++)
1252 {
1253 decl = XCREATENODE (struct decl);
1254 decl->mode = dm_unit;
1255 decl->pos = 0;
1256 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1257 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1258 DECL_UNIT (decl)->query_p = 0;
1259 DECL_UNIT (decl)->min_occ_cycle_num = -1;
1260 DECL_UNIT (decl)->in_set_p = 0;
1261 VEC_safe_push (decl_t,heap, decls, decl);
1262 }
1263 }
1264
1265 /* Process a DEFINE_QUERY_CPU_UNIT.
1266
1267 This gives information about a unit contained in CPU. We fill a
1268 struct unit_decl with information used later by `expand_automata'. */
1269 static void
1270 gen_query_cpu_unit (rtx def)
1271 {
1272 decl_t decl;
1273 char **str_cpu_units;
1274 int vect_length;
1275 int i;
1276
1277 str_cpu_units = get_str_vect (XSTR (def, 0), &vect_length, ',',
1278 FALSE);
1279 if (str_cpu_units == NULL)
1280 fatal ("invalid string `%s' in define_query_cpu_unit", XSTR (def, 0));
1281 for (i = 0; i < vect_length; i++)
1282 {
1283 decl = XCREATENODE (struct decl);
1284 decl->mode = dm_unit;
1285 decl->pos = 0;
1286 DECL_UNIT (decl)->name = check_name (str_cpu_units [i], decl->pos);
1287 DECL_UNIT (decl)->automaton_name = XSTR (def, 1);
1288 DECL_UNIT (decl)->query_p = 1;
1289 VEC_safe_push (decl_t,heap, decls, decl);
1290 }
1291 }
1292
1293 /* Process a DEFINE_BYPASS.
1294
1295 This gives information about a unit contained in the CPU. We fill
1296 in a struct bypass_decl with information used later by
1297 `expand_automata'. */
1298 static void
1299 gen_bypass (rtx def)
1300 {
1301 decl_t decl;
1302 char **out_insns;
1303 int out_length;
1304 char **in_insns;
1305 int in_length;
1306 int i, j;
1307
1308 out_insns = get_str_vect (XSTR (def, 1), &out_length, ',', FALSE);
1309 if (out_insns == NULL)
1310 fatal ("invalid string `%s' in define_bypass", XSTR (def, 1));
1311 in_insns = get_str_vect (XSTR (def, 2), &in_length, ',', FALSE);
1312 if (in_insns == NULL)
1313 fatal ("invalid string `%s' in define_bypass", XSTR (def, 2));
1314 for (i = 0; i < out_length; i++)
1315 for (j = 0; j < in_length; j++)
1316 {
1317 decl = XCREATENODE (struct decl);
1318 decl->mode = dm_bypass;
1319 decl->pos = 0;
1320 DECL_BYPASS (decl)->latency = XINT (def, 0);
1321 DECL_BYPASS (decl)->out_insn_name = out_insns [i];
1322 DECL_BYPASS (decl)->in_insn_name = in_insns [j];
1323 DECL_BYPASS (decl)->bypass_guard_name = XSTR (def, 3);
1324 VEC_safe_push (decl_t,heap, decls, decl);
1325 }
1326 }
1327
1328 /* Process an EXCLUSION_SET.
1329
1330 This gives information about a cpu unit conflicts. We fill a
1331 struct excl_rel_decl (excl) with information used later by
1332 `expand_automata'. */
1333 static void
1334 gen_excl_set (rtx def)
1335 {
1336 decl_t decl;
1337 char **first_str_cpu_units;
1338 char **second_str_cpu_units;
1339 int first_vect_length;
1340 int length;
1341 int i;
1342
1343 first_str_cpu_units
1344 = get_str_vect (XSTR (def, 0), &first_vect_length, ',', FALSE);
1345 if (first_str_cpu_units == NULL)
1346 fatal ("invalid first string `%s' in exclusion_set", XSTR (def, 0));
1347 second_str_cpu_units = get_str_vect (XSTR (def, 1), &length, ',',
1348 FALSE);
1349 if (second_str_cpu_units == NULL)
1350 fatal ("invalid second string `%s' in exclusion_set", XSTR (def, 1));
1351 length += first_vect_length;
1352 decl = XCREATENODEVAR (struct decl, sizeof (struct decl) + (length - 1) * sizeof (char *));
1353 decl->mode = dm_excl;
1354 decl->pos = 0;
1355 DECL_EXCL (decl)->all_names_num = length;
1356 DECL_EXCL (decl)->first_list_length = first_vect_length;
1357 for (i = 0; i < length; i++)
1358 if (i < first_vect_length)
1359 DECL_EXCL (decl)->names [i] = first_str_cpu_units [i];
1360 else
1361 DECL_EXCL (decl)->names [i]
1362 = second_str_cpu_units [i - first_vect_length];
1363 VEC_safe_push (decl_t,heap, decls, decl);
1364 }
1365
1366 /* Process a PRESENCE_SET, a FINAL_PRESENCE_SET, an ABSENCE_SET,
1367 FINAL_ABSENCE_SET (it is depended on PRESENCE_P and FINAL_P).
1368
1369 This gives information about a cpu unit reservation requirements.
1370 We fill a struct unit_pattern_rel_decl with information used later
1371 by `expand_automata'. */
1372 static void
1373 gen_presence_absence_set (rtx def, int presence_p, int final_p)
1374 {
1375 decl_t decl;
1376 char **str_cpu_units;
1377 char **str_pattern_lists;
1378 char ***str_patterns;
1379 int cpu_units_length;
1380 int length;
1381 int patterns_length;
1382 int i;
1383
1384 str_cpu_units = get_str_vect (XSTR (def, 0), &cpu_units_length, ',',
1385 FALSE);
1386 if (str_cpu_units == NULL)
1387 fatal ((presence_p
1388 ? (final_p
1389 ? "invalid first string `%s' in final_presence_set"
1390 : "invalid first string `%s' in presence_set")
1391 : (final_p
1392 ? "invalid first string `%s' in final_absence_set"
1393 : "invalid first string `%s' in absence_set")),
1394 XSTR (def, 0));
1395 str_pattern_lists = get_str_vect (XSTR (def, 1),
1396 &patterns_length, ',', FALSE);
1397 if (str_pattern_lists == NULL)
1398 fatal ((presence_p
1399 ? (final_p
1400 ? "invalid second string `%s' in final_presence_set"
1401 : "invalid second string `%s' in presence_set")
1402 : (final_p
1403 ? "invalid second string `%s' in final_absence_set"
1404 : "invalid second string `%s' in absence_set")), XSTR (def, 1));
1405 str_patterns = XOBNEWVEC (&irp, char **, patterns_length);
1406 for (i = 0; i < patterns_length; i++)
1407 {
1408 str_patterns [i] = get_str_vect (str_pattern_lists [i],
1409 &length, ' ', FALSE);
1410 gcc_assert (str_patterns [i]);
1411 }
1412 decl = XCREATENODE (struct decl);
1413 decl->pos = 0;
1414 if (presence_p)
1415 {
1416 decl->mode = dm_presence;
1417 DECL_PRESENCE (decl)->names_num = cpu_units_length;
1418 DECL_PRESENCE (decl)->names = str_cpu_units;
1419 DECL_PRESENCE (decl)->patterns = str_patterns;
1420 DECL_PRESENCE (decl)->patterns_num = patterns_length;
1421 DECL_PRESENCE (decl)->final_p = final_p;
1422 }
1423 else
1424 {
1425 decl->mode = dm_absence;
1426 DECL_ABSENCE (decl)->names_num = cpu_units_length;
1427 DECL_ABSENCE (decl)->names = str_cpu_units;
1428 DECL_ABSENCE (decl)->patterns = str_patterns;
1429 DECL_ABSENCE (decl)->patterns_num = patterns_length;
1430 DECL_ABSENCE (decl)->final_p = final_p;
1431 }
1432 VEC_safe_push (decl_t,heap, decls, decl);
1433 }
1434
1435 /* Process a PRESENCE_SET.
1436
1437 This gives information about a cpu unit reservation requirements.
1438 We fill a struct unit_pattern_rel_decl (presence) with information
1439 used later by `expand_automata'. */
1440 static void
1441 gen_presence_set (rtx def)
1442 {
1443 gen_presence_absence_set (def, TRUE, FALSE);
1444 }
1445
1446 /* Process a FINAL_PRESENCE_SET.
1447
1448 This gives information about a cpu unit reservation requirements.
1449 We fill a struct unit_pattern_rel_decl (presence) with information
1450 used later by `expand_automata'. */
1451 static void
1452 gen_final_presence_set (rtx def)
1453 {
1454 gen_presence_absence_set (def, TRUE, TRUE);
1455 }
1456
1457 /* Process an ABSENCE_SET.
1458
1459 This gives information about a cpu unit reservation requirements.
1460 We fill a struct unit_pattern_rel_decl (absence) with information
1461 used later by `expand_automata'. */
1462 static void
1463 gen_absence_set (rtx def)
1464 {
1465 gen_presence_absence_set (def, FALSE, FALSE);
1466 }
1467
1468 /* Process a FINAL_ABSENCE_SET.
1469
1470 This gives information about a cpu unit reservation requirements.
1471 We fill a struct unit_pattern_rel_decl (absence) with information
1472 used later by `expand_automata'. */
1473 static void
1474 gen_final_absence_set (rtx def)
1475 {
1476 gen_presence_absence_set (def, FALSE, TRUE);
1477 }
1478
1479 /* Process a DEFINE_AUTOMATON.
1480
1481 This gives information about a finite state automaton used for
1482 recognizing pipeline hazards. We fill a struct automaton_decl
1483 with information used later by `expand_automata'. */
1484 static void
1485 gen_automaton (rtx def)
1486 {
1487 decl_t decl;
1488 char **str_automata;
1489 int vect_length;
1490 int i;
1491
1492 str_automata = get_str_vect (XSTR (def, 0), &vect_length, ',', FALSE);
1493 if (str_automata == NULL)
1494 fatal ("invalid string `%s' in define_automaton", XSTR (def, 0));
1495 for (i = 0; i < vect_length; i++)
1496 {
1497 decl = XCREATENODE (struct decl);
1498 decl->mode = dm_automaton;
1499 decl->pos = 0;
1500 DECL_AUTOMATON (decl)->name = check_name (str_automata [i], decl->pos);
1501 VEC_safe_push (decl_t,heap, decls, decl);
1502 }
1503 }
1504
1505 /* Process an AUTOMATA_OPTION.
1506
1507 This gives information how to generate finite state automaton used
1508 for recognizing pipeline hazards. */
1509 static void
1510 gen_automata_option (rtx def)
1511 {
1512 if (strcmp (XSTR (def, 0), NO_MINIMIZATION_OPTION + 1) == 0)
1513 no_minimization_flag = 1;
1514 else if (strcmp (XSTR (def, 0), TIME_OPTION + 1) == 0)
1515 time_flag = 1;
1516 else if (strcmp (XSTR (def, 0), STATS_OPTION + 1) == 0)
1517 stats_flag = 1;
1518 else if (strcmp (XSTR (def, 0), V_OPTION + 1) == 0)
1519 v_flag = 1;
1520 else if (strcmp (XSTR (def, 0), W_OPTION + 1) == 0)
1521 w_flag = 1;
1522 else if (strcmp (XSTR (def, 0), NDFA_OPTION + 1) == 0)
1523 ndfa_flag = 1;
1524 else if (strcmp (XSTR (def, 0), PROGRESS_OPTION + 1) == 0)
1525 progress_flag = 1;
1526 else
1527 fatal ("invalid option `%s' in automata_option", XSTR (def, 0));
1528 }
1529
1530 /* Name in reservation to denote absence reservation. */
1531 #define NOTHING_NAME "nothing"
1532
1533 /* The following string contains original reservation string being
1534 parsed. */
1535 static const char *reserv_str;
1536
1537 /* Parse an element in STR. */
1538 static regexp_t
1539 gen_regexp_el (const char *str)
1540 {
1541 regexp_t regexp;
1542 char *dstr;
1543 int len;
1544
1545 if (*str == '(')
1546 {
1547 len = strlen (str);
1548 if (str [len - 1] != ')')
1549 fatal ("garbage after ) in reservation `%s'", reserv_str);
1550 dstr = XALLOCAVAR (char, len - 1);
1551 memcpy (dstr, str + 1, len - 2);
1552 dstr [len-2] = '\0';
1553 regexp = gen_regexp_sequence (dstr);
1554 }
1555 else if (strcmp (str, NOTHING_NAME) == 0)
1556 {
1557 regexp = XCREATENODE (struct regexp);
1558 regexp->mode = rm_nothing;
1559 }
1560 else
1561 {
1562 regexp = XCREATENODE (struct regexp);
1563 regexp->mode = rm_unit;
1564 REGEXP_UNIT (regexp)->name = str;
1565 }
1566 return regexp;
1567 }
1568
1569 /* Parse construction `repeat' in STR. */
1570 static regexp_t
1571 gen_regexp_repeat (const char *str)
1572 {
1573 regexp_t regexp;
1574 regexp_t repeat;
1575 char **repeat_vect;
1576 int els_num;
1577 int i;
1578
1579 repeat_vect = get_str_vect (str, &els_num, '*', TRUE);
1580 if (repeat_vect == NULL)
1581 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1582 if (els_num > 1)
1583 {
1584 regexp = gen_regexp_el (repeat_vect [0]);
1585 for (i = 1; i < els_num; i++)
1586 {
1587 repeat = XCREATENODE (struct regexp);
1588 repeat->mode = rm_repeat;
1589 REGEXP_REPEAT (repeat)->regexp = regexp;
1590 REGEXP_REPEAT (repeat)->repeat_num = atoi (repeat_vect [i]);
1591 if (REGEXP_REPEAT (repeat)->repeat_num <= 1)
1592 fatal ("repetition `%s' <= 1 in reservation `%s'",
1593 str, reserv_str);
1594 regexp = repeat;
1595 }
1596 return regexp;
1597 }
1598 else
1599 return gen_regexp_el (str);
1600 }
1601
1602 /* Parse reservation STR which possibly contains separator '+'. */
1603 static regexp_t
1604 gen_regexp_allof (const char *str)
1605 {
1606 regexp_t allof;
1607 char **allof_vect;
1608 int els_num;
1609 int i;
1610
1611 allof_vect = get_str_vect (str, &els_num, '+', TRUE);
1612 if (allof_vect == NULL)
1613 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1614 if (els_num > 1)
1615 {
1616 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1617 + sizeof (regexp_t) * (els_num - 1));
1618 allof->mode = rm_allof;
1619 REGEXP_ALLOF (allof)->regexps_num = els_num;
1620 for (i = 0; i < els_num; i++)
1621 REGEXP_ALLOF (allof)->regexps [i] = gen_regexp_repeat (allof_vect [i]);
1622 return allof;
1623 }
1624 else
1625 return gen_regexp_repeat (str);
1626 }
1627
1628 /* Parse reservation STR which possibly contains separator '|'. */
1629 static regexp_t
1630 gen_regexp_oneof (const char *str)
1631 {
1632 regexp_t oneof;
1633 char **oneof_vect;
1634 int els_num;
1635 int i;
1636
1637 oneof_vect = get_str_vect (str, &els_num, '|', TRUE);
1638 if (oneof_vect == NULL)
1639 fatal ("invalid `%s' in reservation `%s'", str, reserv_str);
1640 if (els_num > 1)
1641 {
1642 oneof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1643 + sizeof (regexp_t) * (els_num - 1));
1644 oneof->mode = rm_oneof;
1645 REGEXP_ONEOF (oneof)->regexps_num = els_num;
1646 for (i = 0; i < els_num; i++)
1647 REGEXP_ONEOF (oneof)->regexps [i] = gen_regexp_allof (oneof_vect [i]);
1648 return oneof;
1649 }
1650 else
1651 return gen_regexp_allof (str);
1652 }
1653
1654 /* Parse reservation STR which possibly contains separator ','. */
1655 static regexp_t
1656 gen_regexp_sequence (const char *str)
1657 {
1658 regexp_t sequence;
1659 char **sequence_vect;
1660 int els_num;
1661 int i;
1662
1663 sequence_vect = get_str_vect (str, &els_num, ',', TRUE);
1664 if (els_num > 1)
1665 {
1666 sequence = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
1667 + sizeof (regexp_t) * (els_num - 1));
1668 sequence->mode = rm_sequence;
1669 REGEXP_SEQUENCE (sequence)->regexps_num = els_num;
1670 for (i = 0; i < els_num; i++)
1671 REGEXP_SEQUENCE (sequence)->regexps [i]
1672 = gen_regexp_oneof (sequence_vect [i]);
1673 return sequence;
1674 }
1675 else
1676 return gen_regexp_oneof (str);
1677 }
1678
1679 /* Parse construction reservation STR. */
1680 static regexp_t
1681 gen_regexp (const char *str)
1682 {
1683 reserv_str = str;
1684 return gen_regexp_sequence (str);;
1685 }
1686
1687 /* Process a DEFINE_RESERVATION.
1688
1689 This gives information about a reservation of cpu units. We fill
1690 in a struct reserv_decl with information used later by
1691 `expand_automata'. */
1692 static void
1693 gen_reserv (rtx def)
1694 {
1695 decl_t decl;
1696
1697 decl = XCREATENODE (struct decl);
1698 decl->mode = dm_reserv;
1699 decl->pos = 0;
1700 DECL_RESERV (decl)->name = check_name (XSTR (def, 0), decl->pos);
1701 DECL_RESERV (decl)->regexp = gen_regexp (XSTR (def, 1));
1702 VEC_safe_push (decl_t,heap, decls, decl);
1703 }
1704
1705 /* Process a DEFINE_INSN_RESERVATION.
1706
1707 This gives information about the reservation of cpu units by an
1708 insn. We fill a struct insn_reserv_decl with information used
1709 later by `expand_automata'. */
1710 static void
1711 gen_insn_reserv (rtx def)
1712 {
1713 decl_t decl;
1714
1715 decl = XCREATENODE (struct decl);
1716 decl->mode = dm_insn_reserv;
1717 decl->pos = 0;
1718 DECL_INSN_RESERV (decl)->name
1719 = check_name (XSTR (def, 0), decl->pos);
1720 DECL_INSN_RESERV (decl)->default_latency = XINT (def, 1);
1721 DECL_INSN_RESERV (decl)->condexp = XEXP (def, 2);
1722 DECL_INSN_RESERV (decl)->regexp = gen_regexp (XSTR (def, 3));
1723 VEC_safe_push (decl_t,heap, decls, decl);
1724 }
1725
1726
1727
1728 /* The function evaluates hash value (0..UINT_MAX) of string. */
1729 static unsigned
1730 string_hash (const char *string)
1731 {
1732 unsigned result, i;
1733
1734 for (result = i = 0;*string++ != '\0'; i++)
1735 result += ((unsigned char) *string << (i % CHAR_BIT));
1736 return result;
1737 }
1738
1739
1740
1741 /* This page contains abstract data `table of automaton declarations'.
1742 Elements of the table is nodes representing automaton declarations.
1743 Key of the table elements is name of given automaton. Remember
1744 that automaton names have own space. */
1745
1746 /* The function evaluates hash value of an automaton declaration. The
1747 function is used by abstract data `hashtab'. The function returns
1748 hash value (0..UINT_MAX) of given automaton declaration. */
1749 static hashval_t
1750 automaton_decl_hash (const void *automaton_decl)
1751 {
1752 const_decl_t const decl = (const_decl_t) automaton_decl;
1753
1754 gcc_assert (decl->mode != dm_automaton
1755 || DECL_AUTOMATON (decl)->name);
1756 return string_hash (DECL_AUTOMATON (decl)->name);
1757 }
1758
1759 /* The function tests automaton declarations on equality of their
1760 keys. The function is used by abstract data `hashtab'. The
1761 function returns 1 if the declarations have the same key, 0
1762 otherwise. */
1763 static int
1764 automaton_decl_eq_p (const void* automaton_decl_1,
1765 const void* automaton_decl_2)
1766 {
1767 const_decl_t const decl1 = (const_decl_t) automaton_decl_1;
1768 const_decl_t const decl2 = (const_decl_t) automaton_decl_2;
1769
1770 gcc_assert (decl1->mode == dm_automaton
1771 && DECL_AUTOMATON (decl1)->name
1772 && decl2->mode == dm_automaton
1773 && DECL_AUTOMATON (decl2)->name);
1774 return strcmp (DECL_AUTOMATON (decl1)->name,
1775 DECL_AUTOMATON (decl2)->name) == 0;
1776 }
1777
1778 /* The automaton declaration table itself is represented by the
1779 following variable. */
1780 static htab_t automaton_decl_table;
1781
1782 /* The function inserts automaton declaration into the table. The
1783 function does nothing if an automaton declaration with the same key
1784 exists already in the table. The function returns automaton
1785 declaration node in the table with the same key as given automaton
1786 declaration node. */
1787 static decl_t
1788 insert_automaton_decl (decl_t automaton_decl)
1789 {
1790 void **entry_ptr;
1791
1792 entry_ptr = htab_find_slot (automaton_decl_table, automaton_decl, 1);
1793 if (*entry_ptr == NULL)
1794 *entry_ptr = (void *) automaton_decl;
1795 return (decl_t) *entry_ptr;
1796 }
1797
1798 /* The following variable value is node representing automaton
1799 declaration. The node used for searching automaton declaration
1800 with given name. */
1801 static struct decl work_automaton_decl;
1802
1803 /* The function searches for automaton declaration in the table with
1804 the same key as node representing name of the automaton
1805 declaration. The function returns node found in the table, NULL if
1806 such node does not exist in the table. */
1807 static decl_t
1808 find_automaton_decl (const char *name)
1809 {
1810 void *entry;
1811
1812 work_automaton_decl.mode = dm_automaton;
1813 DECL_AUTOMATON (&work_automaton_decl)->name = name;
1814 entry = htab_find (automaton_decl_table, &work_automaton_decl);
1815 return (decl_t) entry;
1816 }
1817
1818 /* The function creates empty automaton declaration table and node
1819 representing automaton declaration and used for searching automaton
1820 declaration with given name. The function must be called only once
1821 before any work with the automaton declaration table. */
1822 static void
1823 initiate_automaton_decl_table (void)
1824 {
1825 work_automaton_decl.mode = dm_automaton;
1826 automaton_decl_table = htab_create (10, automaton_decl_hash,
1827 automaton_decl_eq_p, (htab_del) 0);
1828 }
1829
1830 /* The function deletes the automaton declaration table. Only call of
1831 function `initiate_automaton_decl_table' is possible immediately
1832 after this function call. */
1833 static void
1834 finish_automaton_decl_table (void)
1835 {
1836 htab_delete (automaton_decl_table);
1837 }
1838
1839
1840
1841 /* This page contains abstract data `table of insn declarations'.
1842 Elements of the table is nodes representing insn declarations. Key
1843 of the table elements is name of given insn (in corresponding
1844 define_insn_reservation). Remember that insn names have own
1845 space. */
1846
1847 /* The function evaluates hash value of an insn declaration. The
1848 function is used by abstract data `hashtab'. The function returns
1849 hash value (0..UINT_MAX) of given insn declaration. */
1850 static hashval_t
1851 insn_decl_hash (const void *insn_decl)
1852 {
1853 const_decl_t const decl = (const_decl_t) insn_decl;
1854
1855 gcc_assert (decl->mode == dm_insn_reserv
1856 && DECL_INSN_RESERV (decl)->name);
1857 return string_hash (DECL_INSN_RESERV (decl)->name);
1858 }
1859
1860 /* The function tests insn declarations on equality of their keys.
1861 The function is used by abstract data `hashtab'. The function
1862 returns 1 if declarations have the same key, 0 otherwise. */
1863 static int
1864 insn_decl_eq_p (const void *insn_decl_1, const void *insn_decl_2)
1865 {
1866 const_decl_t const decl1 = (const_decl_t) insn_decl_1;
1867 const_decl_t const decl2 = (const_decl_t) insn_decl_2;
1868
1869 gcc_assert (decl1->mode == dm_insn_reserv
1870 && DECL_INSN_RESERV (decl1)->name
1871 && decl2->mode == dm_insn_reserv
1872 && DECL_INSN_RESERV (decl2)->name);
1873 return strcmp (DECL_INSN_RESERV (decl1)->name,
1874 DECL_INSN_RESERV (decl2)->name) == 0;
1875 }
1876
1877 /* The insn declaration table itself is represented by the following
1878 variable. The table does not contain insn reservation
1879 declarations. */
1880 static htab_t insn_decl_table;
1881
1882 /* The function inserts insn declaration into the table. The function
1883 does nothing if an insn declaration with the same key exists
1884 already in the table. The function returns insn declaration node
1885 in the table with the same key as given insn declaration node. */
1886 static decl_t
1887 insert_insn_decl (decl_t insn_decl)
1888 {
1889 void **entry_ptr;
1890
1891 entry_ptr = htab_find_slot (insn_decl_table, insn_decl, 1);
1892 if (*entry_ptr == NULL)
1893 *entry_ptr = (void *) insn_decl;
1894 return (decl_t) *entry_ptr;
1895 }
1896
1897 /* The following variable value is node representing insn reservation
1898 declaration. The node used for searching insn reservation
1899 declaration with given name. */
1900 static struct decl work_insn_decl;
1901
1902 /* The function searches for insn reservation declaration in the table
1903 with the same key as node representing name of the insn reservation
1904 declaration. The function returns node found in the table, NULL if
1905 such node does not exist in the table. */
1906 static decl_t
1907 find_insn_decl (const char *name)
1908 {
1909 void *entry;
1910
1911 work_insn_decl.mode = dm_insn_reserv;
1912 DECL_INSN_RESERV (&work_insn_decl)->name = name;
1913 entry = htab_find (insn_decl_table, &work_insn_decl);
1914 return (decl_t) entry;
1915 }
1916
1917 /* The function creates empty insn declaration table and node
1918 representing insn declaration and used for searching insn
1919 declaration with given name. The function must be called only once
1920 before any work with the insn declaration table. */
1921 static void
1922 initiate_insn_decl_table (void)
1923 {
1924 work_insn_decl.mode = dm_insn_reserv;
1925 insn_decl_table = htab_create (10, insn_decl_hash, insn_decl_eq_p,
1926 (htab_del) 0);
1927 }
1928
1929 /* The function deletes the insn declaration table. Only call of
1930 function `initiate_insn_decl_table' is possible immediately after
1931 this function call. */
1932 static void
1933 finish_insn_decl_table (void)
1934 {
1935 htab_delete (insn_decl_table);
1936 }
1937
1938
1939
1940 /* This page contains abstract data `table of declarations'. Elements
1941 of the table is nodes representing declarations (of units and
1942 reservations). Key of the table elements is names of given
1943 declarations. */
1944
1945 /* The function evaluates hash value of a declaration. The function
1946 is used by abstract data `hashtab'. The function returns hash
1947 value (0..UINT_MAX) of given declaration. */
1948 static hashval_t
1949 decl_hash (const void *decl)
1950 {
1951 const_decl_t const d = (const_decl_t) decl;
1952
1953 gcc_assert ((d->mode == dm_unit && DECL_UNIT (d)->name)
1954 || (d->mode == dm_reserv && DECL_RESERV (d)->name));
1955 return string_hash (d->mode == dm_unit
1956 ? DECL_UNIT (d)->name : DECL_RESERV (d)->name);
1957 }
1958
1959 /* The function tests declarations on equality of their keys. The
1960 function is used by abstract data 'hashtab'. The function
1961 returns 1 if the declarations have the same key, 0 otherwise. */
1962 static int
1963 decl_eq_p (const void *decl_1, const void *decl_2)
1964 {
1965 const_decl_t const d1 = (const_decl_t) decl_1;
1966 const_decl_t const d2 = (const_decl_t) decl_2;
1967
1968 gcc_assert ((d1->mode == dm_unit && DECL_UNIT (d1)->name)
1969 || (d1->mode == dm_reserv && DECL_RESERV (d1)->name));
1970 gcc_assert ((d2->mode == dm_unit && DECL_UNIT (d2)->name)
1971 || (d2->mode == dm_reserv && DECL_RESERV (d2)->name));
1972 return strcmp ((d1->mode == dm_unit
1973 ? DECL_UNIT (d1)->name : DECL_RESERV (d1)->name),
1974 (d2->mode == dm_unit
1975 ? DECL_UNIT (d2)->name : DECL_RESERV (d2)->name)) == 0;
1976 }
1977
1978 /* The declaration table itself is represented by the following
1979 variable. */
1980 static htab_t decl_table;
1981
1982 /* The function inserts declaration into the table. The function does
1983 nothing if a declaration with the same key exists already in the
1984 table. The function returns declaration node in the table with the
1985 same key as given declaration node. */
1986
1987 static decl_t
1988 insert_decl (decl_t decl)
1989 {
1990 void **entry_ptr;
1991
1992 entry_ptr = htab_find_slot (decl_table, decl, 1);
1993 if (*entry_ptr == NULL)
1994 *entry_ptr = (void *) decl;
1995 return (decl_t) *entry_ptr;
1996 }
1997
1998 /* The following variable value is node representing declaration. The
1999 node used for searching declaration with given name. */
2000 static struct decl work_decl;
2001
2002 /* The function searches for declaration in the table with the same
2003 key as node representing name of the declaration. The function
2004 returns node found in the table, NULL if such node does not exist
2005 in the table. */
2006 static decl_t
2007 find_decl (const char *name)
2008 {
2009 void *entry;
2010
2011 work_decl.mode = dm_unit;
2012 DECL_UNIT (&work_decl)->name = name;
2013 entry = htab_find (decl_table, &work_decl);
2014 return (decl_t) entry;
2015 }
2016
2017 /* The function creates empty declaration table and node representing
2018 declaration and used for searching declaration with given name.
2019 The function must be called only once before any work with the
2020 declaration table. */
2021 static void
2022 initiate_decl_table (void)
2023 {
2024 work_decl.mode = dm_unit;
2025 decl_table = htab_create (10, decl_hash, decl_eq_p, (htab_del) 0);
2026 }
2027
2028 /* The function deletes the declaration table. Only call of function
2029 `initiate_declaration_table' is possible immediately after this
2030 function call. */
2031 static void
2032 finish_decl_table (void)
2033 {
2034 htab_delete (decl_table);
2035 }
2036
2037
2038
2039 /* This page contains checker of pipeline hazard description. */
2040
2041 /* Checking NAMES in an exclusion clause vector and returning formed
2042 unit_set_el_list. */
2043 static unit_set_el_t
2044 process_excls (char **names, int num, pos_t excl_pos ATTRIBUTE_UNUSED)
2045 {
2046 unit_set_el_t el_list;
2047 unit_set_el_t last_el;
2048 unit_set_el_t new_el;
2049 decl_t decl_in_table;
2050 int i;
2051
2052 el_list = NULL;
2053 last_el = NULL;
2054 for (i = 0; i < num; i++)
2055 {
2056 decl_in_table = find_decl (names [i]);
2057 if (decl_in_table == NULL)
2058 error ("unit `%s' in exclusion is not declared", names [i]);
2059 else if (decl_in_table->mode != dm_unit)
2060 error ("`%s' in exclusion is not unit", names [i]);
2061 else
2062 {
2063 new_el = XCREATENODE (struct unit_set_el);
2064 new_el->unit_decl = DECL_UNIT (decl_in_table);
2065 new_el->next_unit_set_el = NULL;
2066 if (last_el == NULL)
2067 el_list = last_el = new_el;
2068 else
2069 {
2070 last_el->next_unit_set_el = new_el;
2071 last_el = last_el->next_unit_set_el;
2072 }
2073 }
2074 }
2075 return el_list;
2076 }
2077
2078 /* The function adds each element from SOURCE_LIST to the exclusion
2079 list of the each element from DEST_LIST. Checking situation "unit
2080 excludes itself". */
2081 static void
2082 add_excls (unit_set_el_t dest_list, unit_set_el_t source_list,
2083 pos_t excl_pos ATTRIBUTE_UNUSED)
2084 {
2085 unit_set_el_t dst;
2086 unit_set_el_t src;
2087 unit_set_el_t curr_el;
2088 unit_set_el_t prev_el;
2089 unit_set_el_t copy;
2090
2091 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2092 for (src = source_list; src != NULL; src = src->next_unit_set_el)
2093 {
2094 if (dst->unit_decl == src->unit_decl)
2095 {
2096 error ("unit `%s' excludes itself", src->unit_decl->name);
2097 continue;
2098 }
2099 if (dst->unit_decl->automaton_name != NULL
2100 && src->unit_decl->automaton_name != NULL
2101 && strcmp (dst->unit_decl->automaton_name,
2102 src->unit_decl->automaton_name) != 0)
2103 {
2104 error ("units `%s' and `%s' in exclusion set belong to different automata",
2105 src->unit_decl->name, dst->unit_decl->name);
2106 continue;
2107 }
2108 for (curr_el = dst->unit_decl->excl_list, prev_el = NULL;
2109 curr_el != NULL;
2110 prev_el = curr_el, curr_el = curr_el->next_unit_set_el)
2111 if (curr_el->unit_decl == src->unit_decl)
2112 break;
2113 if (curr_el == NULL)
2114 {
2115 /* Element not found - insert. */
2116 copy = XCOPYNODE (struct unit_set_el, src);
2117 copy->next_unit_set_el = NULL;
2118 if (prev_el == NULL)
2119 dst->unit_decl->excl_list = copy;
2120 else
2121 prev_el->next_unit_set_el = copy;
2122 }
2123 }
2124 }
2125
2126 /* Checking NAMES in presence/absence clause and returning the
2127 formed unit_set_el_list. The function is called only after
2128 processing all exclusion sets. */
2129 static unit_set_el_t
2130 process_presence_absence_names (char **names, int num,
2131 pos_t req_pos ATTRIBUTE_UNUSED,
2132 int presence_p, int final_p)
2133 {
2134 unit_set_el_t el_list;
2135 unit_set_el_t last_el;
2136 unit_set_el_t new_el;
2137 decl_t decl_in_table;
2138 int i;
2139
2140 el_list = NULL;
2141 last_el = NULL;
2142 for (i = 0; i < num; i++)
2143 {
2144 decl_in_table = find_decl (names [i]);
2145 if (decl_in_table == NULL)
2146 error ((presence_p
2147 ? (final_p
2148 ? "unit `%s' in final presence set is not declared"
2149 : "unit `%s' in presence set is not declared")
2150 : (final_p
2151 ? "unit `%s' in final absence set is not declared"
2152 : "unit `%s' in absence set is not declared")), names [i]);
2153 else if (decl_in_table->mode != dm_unit)
2154 error ((presence_p
2155 ? (final_p
2156 ? "`%s' in final presence set is not unit"
2157 : "`%s' in presence set is not unit")
2158 : (final_p
2159 ? "`%s' in final absence set is not unit"
2160 : "`%s' in absence set is not unit")), names [i]);
2161 else
2162 {
2163 new_el = XCREATENODE (struct unit_set_el);
2164 new_el->unit_decl = DECL_UNIT (decl_in_table);
2165 new_el->next_unit_set_el = NULL;
2166 if (last_el == NULL)
2167 el_list = last_el = new_el;
2168 else
2169 {
2170 last_el->next_unit_set_el = new_el;
2171 last_el = last_el->next_unit_set_el;
2172 }
2173 }
2174 }
2175 return el_list;
2176 }
2177
2178 /* Checking NAMES in patterns of a presence/absence clause and
2179 returning the formed pattern_set_el_list. The function is called
2180 only after processing all exclusion sets. */
2181 static pattern_set_el_t
2182 process_presence_absence_patterns (char ***patterns, int num,
2183 pos_t req_pos ATTRIBUTE_UNUSED,
2184 int presence_p, int final_p)
2185 {
2186 pattern_set_el_t el_list;
2187 pattern_set_el_t last_el;
2188 pattern_set_el_t new_el;
2189 decl_t decl_in_table;
2190 int i, j;
2191
2192 el_list = NULL;
2193 last_el = NULL;
2194 for (i = 0; i < num; i++)
2195 {
2196 for (j = 0; patterns [i] [j] != NULL; j++)
2197 ;
2198 new_el = XCREATENODEVAR (struct pattern_set_el,
2199 sizeof (struct pattern_set_el)
2200 + sizeof (struct unit_decl *) * j);
2201 new_el->unit_decls
2202 = (struct unit_decl **) ((char *) new_el
2203 + sizeof (struct pattern_set_el));
2204 new_el->next_pattern_set_el = NULL;
2205 if (last_el == NULL)
2206 el_list = last_el = new_el;
2207 else
2208 {
2209 last_el->next_pattern_set_el = new_el;
2210 last_el = last_el->next_pattern_set_el;
2211 }
2212 new_el->units_num = 0;
2213 for (j = 0; patterns [i] [j] != NULL; j++)
2214 {
2215 decl_in_table = find_decl (patterns [i] [j]);
2216 if (decl_in_table == NULL)
2217 error ((presence_p
2218 ? (final_p
2219 ? "unit `%s' in final presence set is not declared"
2220 : "unit `%s' in presence set is not declared")
2221 : (final_p
2222 ? "unit `%s' in final absence set is not declared"
2223 : "unit `%s' in absence set is not declared")),
2224 patterns [i] [j]);
2225 else if (decl_in_table->mode != dm_unit)
2226 error ((presence_p
2227 ? (final_p
2228 ? "`%s' in final presence set is not unit"
2229 : "`%s' in presence set is not unit")
2230 : (final_p
2231 ? "`%s' in final absence set is not unit"
2232 : "`%s' in absence set is not unit")),
2233 patterns [i] [j]);
2234 else
2235 {
2236 new_el->unit_decls [new_el->units_num]
2237 = DECL_UNIT (decl_in_table);
2238 new_el->units_num++;
2239 }
2240 }
2241 }
2242 return el_list;
2243 }
2244
2245 /* The function adds each element from PATTERN_LIST to presence (if
2246 PRESENCE_P) or absence list of the each element from DEST_LIST.
2247 Checking situations "unit requires own absence", and "unit excludes
2248 and requires presence of ...", "unit requires absence and presence
2249 of ...", "units in (final) presence set belong to different
2250 automata", and "units in (final) absence set belong to different
2251 automata". Remember that we process absence sets only after all
2252 presence sets. */
2253 static void
2254 add_presence_absence (unit_set_el_t dest_list,
2255 pattern_set_el_t pattern_list,
2256 pos_t req_pos ATTRIBUTE_UNUSED,
2257 int presence_p, int final_p)
2258 {
2259 unit_set_el_t dst;
2260 pattern_set_el_t pat;
2261 struct unit_decl *unit;
2262 unit_set_el_t curr_excl_el;
2263 pattern_set_el_t curr_pat_el;
2264 pattern_set_el_t prev_el;
2265 pattern_set_el_t copy;
2266 int i;
2267 int no_error_flag;
2268
2269 for (dst = dest_list; dst != NULL; dst = dst->next_unit_set_el)
2270 for (pat = pattern_list; pat != NULL; pat = pat->next_pattern_set_el)
2271 {
2272 for (i = 0; i < pat->units_num; i++)
2273 {
2274 unit = pat->unit_decls [i];
2275 if (dst->unit_decl == unit && pat->units_num == 1 && !presence_p)
2276 {
2277 error ("unit `%s' requires own absence", unit->name);
2278 continue;
2279 }
2280 if (dst->unit_decl->automaton_name != NULL
2281 && unit->automaton_name != NULL
2282 && strcmp (dst->unit_decl->automaton_name,
2283 unit->automaton_name) != 0)
2284 {
2285 error ((presence_p
2286 ? (final_p
2287 ? "units `%s' and `%s' in final presence set belong to different automata"
2288 : "units `%s' and `%s' in presence set belong to different automata")
2289 : (final_p
2290 ? "units `%s' and `%s' in final absence set belong to different automata"
2291 : "units `%s' and `%s' in absence set belong to different automata")),
2292 unit->name, dst->unit_decl->name);
2293 continue;
2294 }
2295 no_error_flag = 1;
2296 if (presence_p)
2297 for (curr_excl_el = dst->unit_decl->excl_list;
2298 curr_excl_el != NULL;
2299 curr_excl_el = curr_excl_el->next_unit_set_el)
2300 {
2301 if (unit == curr_excl_el->unit_decl && pat->units_num == 1)
2302 {
2303 if (!w_flag)
2304 {
2305 error ("unit `%s' excludes and requires presence of `%s'",
2306 dst->unit_decl->name, unit->name);
2307 no_error_flag = 0;
2308 }
2309 else
2310 warning
2311 (0, "unit `%s' excludes and requires presence of `%s'",
2312 dst->unit_decl->name, unit->name);
2313 }
2314 }
2315 else if (pat->units_num == 1)
2316 for (curr_pat_el = dst->unit_decl->presence_list;
2317 curr_pat_el != NULL;
2318 curr_pat_el = curr_pat_el->next_pattern_set_el)
2319 if (curr_pat_el->units_num == 1
2320 && unit == curr_pat_el->unit_decls [0])
2321 {
2322 if (!w_flag)
2323 {
2324 error
2325 ("unit `%s' requires absence and presence of `%s'",
2326 dst->unit_decl->name, unit->name);
2327 no_error_flag = 0;
2328 }
2329 else
2330 warning
2331 (0, "unit `%s' requires absence and presence of `%s'",
2332 dst->unit_decl->name, unit->name);
2333 }
2334 if (no_error_flag)
2335 {
2336 for (prev_el = (presence_p
2337 ? (final_p
2338 ? dst->unit_decl->final_presence_list
2339 : dst->unit_decl->final_presence_list)
2340 : (final_p
2341 ? dst->unit_decl->final_absence_list
2342 : dst->unit_decl->absence_list));
2343 prev_el != NULL && prev_el->next_pattern_set_el != NULL;
2344 prev_el = prev_el->next_pattern_set_el)
2345 ;
2346 copy = XCOPYNODE (struct pattern_set_el, pat);
2347 copy->next_pattern_set_el = NULL;
2348 if (prev_el == NULL)
2349 {
2350 if (presence_p)
2351 {
2352 if (final_p)
2353 dst->unit_decl->final_presence_list = copy;
2354 else
2355 dst->unit_decl->presence_list = copy;
2356 }
2357 else if (final_p)
2358 dst->unit_decl->final_absence_list = copy;
2359 else
2360 dst->unit_decl->absence_list = copy;
2361 }
2362 else
2363 prev_el->next_pattern_set_el = copy;
2364 }
2365 }
2366 }
2367 }
2368
2369
2370 /* The function searches for bypass with given IN_INSN_RESERV in given
2371 BYPASS_LIST. */
2372 static struct bypass_decl *
2373 find_bypass (struct bypass_decl *bypass_list,
2374 struct insn_reserv_decl *in_insn_reserv)
2375 {
2376 struct bypass_decl *bypass;
2377
2378 for (bypass = bypass_list; bypass != NULL; bypass = bypass->next)
2379 if (bypass->in_insn_reserv == in_insn_reserv)
2380 break;
2381 return bypass;
2382 }
2383
2384 /* The function processes pipeline description declarations, checks
2385 their correctness, and forms exclusion/presence/absence sets. */
2386 static void
2387 process_decls (void)
2388 {
2389 decl_t decl;
2390 decl_t automaton_decl;
2391 decl_t decl_in_table;
2392 decl_t out_insn_reserv;
2393 decl_t in_insn_reserv;
2394 struct bypass_decl *bypass;
2395 int automaton_presence;
2396 int i;
2397
2398 /* Checking repeated automata declarations. */
2399 automaton_presence = 0;
2400 for (i = 0; i < description->decls_num; i++)
2401 {
2402 decl = description->decls [i];
2403 if (decl->mode == dm_automaton)
2404 {
2405 automaton_presence = 1;
2406 decl_in_table = insert_automaton_decl (decl);
2407 if (decl_in_table != decl)
2408 {
2409 if (!w_flag)
2410 error ("repeated declaration of automaton `%s'",
2411 DECL_AUTOMATON (decl)->name);
2412 else
2413 warning (0, "repeated declaration of automaton `%s'",
2414 DECL_AUTOMATON (decl)->name);
2415 }
2416 }
2417 }
2418 /* Checking undeclared automata, repeated declarations (except for
2419 automata) and correctness of their attributes (insn latency times
2420 etc.). */
2421 for (i = 0; i < description->decls_num; i++)
2422 {
2423 decl = description->decls [i];
2424 if (decl->mode == dm_insn_reserv)
2425 {
2426 if (DECL_INSN_RESERV (decl)->default_latency < 0)
2427 error ("define_insn_reservation `%s' has negative latency time",
2428 DECL_INSN_RESERV (decl)->name);
2429 DECL_INSN_RESERV (decl)->insn_num = description->insns_num;
2430 description->insns_num++;
2431 decl_in_table = insert_insn_decl (decl);
2432 if (decl_in_table != decl)
2433 error ("`%s' is already used as insn reservation name",
2434 DECL_INSN_RESERV (decl)->name);
2435 }
2436 else if (decl->mode == dm_bypass)
2437 {
2438 if (DECL_BYPASS (decl)->latency < 0)
2439 error ("define_bypass `%s - %s' has negative latency time",
2440 DECL_BYPASS (decl)->out_insn_name,
2441 DECL_BYPASS (decl)->in_insn_name);
2442 }
2443 else if (decl->mode == dm_unit || decl->mode == dm_reserv)
2444 {
2445 if (decl->mode == dm_unit)
2446 {
2447 DECL_UNIT (decl)->automaton_decl = NULL;
2448 if (DECL_UNIT (decl)->automaton_name != NULL)
2449 {
2450 automaton_decl
2451 = find_automaton_decl (DECL_UNIT (decl)->automaton_name);
2452 if (automaton_decl == NULL)
2453 error ("automaton `%s' is not declared",
2454 DECL_UNIT (decl)->automaton_name);
2455 else
2456 {
2457 DECL_AUTOMATON (automaton_decl)->automaton_is_used = 1;
2458 DECL_UNIT (decl)->automaton_decl
2459 = DECL_AUTOMATON (automaton_decl);
2460 }
2461 }
2462 else if (automaton_presence)
2463 error ("define_unit `%s' without automaton when one defined",
2464 DECL_UNIT (decl)->name);
2465 DECL_UNIT (decl)->unit_num = description->units_num;
2466 description->units_num++;
2467 if (strcmp (DECL_UNIT (decl)->name, NOTHING_NAME) == 0)
2468 {
2469 error ("`%s' is declared as cpu unit", NOTHING_NAME);
2470 continue;
2471 }
2472 decl_in_table = find_decl (DECL_UNIT (decl)->name);
2473 }
2474 else
2475 {
2476 if (strcmp (DECL_RESERV (decl)->name, NOTHING_NAME) == 0)
2477 {
2478 error ("`%s' is declared as cpu reservation", NOTHING_NAME);
2479 continue;
2480 }
2481 decl_in_table = find_decl (DECL_RESERV (decl)->name);
2482 }
2483 if (decl_in_table == NULL)
2484 decl_in_table = insert_decl (decl);
2485 else
2486 {
2487 if (decl->mode == dm_unit)
2488 error ("repeated declaration of unit `%s'",
2489 DECL_UNIT (decl)->name);
2490 else
2491 error ("repeated declaration of reservation `%s'",
2492 DECL_RESERV (decl)->name);
2493 }
2494 }
2495 }
2496 /* Check bypasses and form list of bypasses for each (output)
2497 insn. */
2498 for (i = 0; i < description->decls_num; i++)
2499 {
2500 decl = description->decls [i];
2501 if (decl->mode == dm_bypass)
2502 {
2503 out_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->out_insn_name);
2504 in_insn_reserv = find_insn_decl (DECL_BYPASS (decl)->in_insn_name);
2505 if (out_insn_reserv == NULL)
2506 error ("there is no insn reservation `%s'",
2507 DECL_BYPASS (decl)->out_insn_name);
2508 else if (in_insn_reserv == NULL)
2509 error ("there is no insn reservation `%s'",
2510 DECL_BYPASS (decl)->in_insn_name);
2511 else
2512 {
2513 DECL_BYPASS (decl)->out_insn_reserv
2514 = DECL_INSN_RESERV (out_insn_reserv);
2515 DECL_BYPASS (decl)->in_insn_reserv
2516 = DECL_INSN_RESERV (in_insn_reserv);
2517 bypass
2518 = find_bypass (DECL_INSN_RESERV (out_insn_reserv)->bypass_list,
2519 DECL_BYPASS (decl)->in_insn_reserv);
2520 if (bypass != NULL)
2521 {
2522 if (DECL_BYPASS (decl)->latency == bypass->latency)
2523 {
2524 if (!w_flag)
2525 error
2526 ("the same bypass `%s - %s' is already defined",
2527 DECL_BYPASS (decl)->out_insn_name,
2528 DECL_BYPASS (decl)->in_insn_name);
2529 else
2530 warning
2531 (0, "the same bypass `%s - %s' is already defined",
2532 DECL_BYPASS (decl)->out_insn_name,
2533 DECL_BYPASS (decl)->in_insn_name);
2534 }
2535 else
2536 error ("bypass `%s - %s' is already defined",
2537 DECL_BYPASS (decl)->out_insn_name,
2538 DECL_BYPASS (decl)->in_insn_name);
2539 }
2540 else
2541 {
2542 DECL_BYPASS (decl)->next
2543 = DECL_INSN_RESERV (out_insn_reserv)->bypass_list;
2544 DECL_INSN_RESERV (out_insn_reserv)->bypass_list
2545 = DECL_BYPASS (decl);
2546 }
2547 }
2548 }
2549 }
2550
2551 /* Check exclusion set declarations and form exclusion sets. */
2552 for (i = 0; i < description->decls_num; i++)
2553 {
2554 decl = description->decls [i];
2555 if (decl->mode == dm_excl)
2556 {
2557 unit_set_el_t unit_set_el_list;
2558 unit_set_el_t unit_set_el_list_2;
2559
2560 unit_set_el_list
2561 = process_excls (DECL_EXCL (decl)->names,
2562 DECL_EXCL (decl)->first_list_length, decl->pos);
2563 unit_set_el_list_2
2564 = process_excls (&DECL_EXCL (decl)->names
2565 [DECL_EXCL (decl)->first_list_length],
2566 DECL_EXCL (decl)->all_names_num
2567 - DECL_EXCL (decl)->first_list_length,
2568 decl->pos);
2569 add_excls (unit_set_el_list, unit_set_el_list_2, decl->pos);
2570 add_excls (unit_set_el_list_2, unit_set_el_list, decl->pos);
2571 }
2572 }
2573
2574 /* Check presence set declarations and form presence sets. */
2575 for (i = 0; i < description->decls_num; i++)
2576 {
2577 decl = description->decls [i];
2578 if (decl->mode == dm_presence)
2579 {
2580 unit_set_el_t unit_set_el_list;
2581 pattern_set_el_t pattern_set_el_list;
2582
2583 unit_set_el_list
2584 = process_presence_absence_names
2585 (DECL_PRESENCE (decl)->names, DECL_PRESENCE (decl)->names_num,
2586 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2587 pattern_set_el_list
2588 = process_presence_absence_patterns
2589 (DECL_PRESENCE (decl)->patterns,
2590 DECL_PRESENCE (decl)->patterns_num,
2591 decl->pos, TRUE, DECL_PRESENCE (decl)->final_p);
2592 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2593 decl->pos, TRUE,
2594 DECL_PRESENCE (decl)->final_p);
2595 }
2596 }
2597
2598 /* Check absence set declarations and form absence sets. */
2599 for (i = 0; i < description->decls_num; i++)
2600 {
2601 decl = description->decls [i];
2602 if (decl->mode == dm_absence)
2603 {
2604 unit_set_el_t unit_set_el_list;
2605 pattern_set_el_t pattern_set_el_list;
2606
2607 unit_set_el_list
2608 = process_presence_absence_names
2609 (DECL_ABSENCE (decl)->names, DECL_ABSENCE (decl)->names_num,
2610 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2611 pattern_set_el_list
2612 = process_presence_absence_patterns
2613 (DECL_ABSENCE (decl)->patterns,
2614 DECL_ABSENCE (decl)->patterns_num,
2615 decl->pos, FALSE, DECL_ABSENCE (decl)->final_p);
2616 add_presence_absence (unit_set_el_list, pattern_set_el_list,
2617 decl->pos, FALSE,
2618 DECL_ABSENCE (decl)->final_p);
2619 }
2620 }
2621 }
2622
2623 /* The following function checks that declared automaton is used. If
2624 the automaton is not used, the function fixes error/warning. The
2625 following function must be called only after `process_decls'. */
2626 static void
2627 check_automaton_usage (void)
2628 {
2629 decl_t decl;
2630 int i;
2631
2632 for (i = 0; i < description->decls_num; i++)
2633 {
2634 decl = description->decls [i];
2635 if (decl->mode == dm_automaton
2636 && !DECL_AUTOMATON (decl)->automaton_is_used)
2637 {
2638 if (!w_flag)
2639 error ("automaton `%s' is not used", DECL_AUTOMATON (decl)->name);
2640 else
2641 warning (0, "automaton `%s' is not used",
2642 DECL_AUTOMATON (decl)->name);
2643 }
2644 }
2645 }
2646
2647 /* The following recursive function processes all regexp in order to
2648 fix usage of units or reservations and to fix errors of undeclared
2649 name. The function may change unit_regexp onto reserv_regexp.
2650 Remember that reserv_regexp does not exist before the function
2651 call. */
2652 static regexp_t
2653 process_regexp (regexp_t regexp)
2654 {
2655 decl_t decl_in_table;
2656 regexp_t new_regexp;
2657 int i;
2658
2659 switch (regexp->mode)
2660 {
2661 case rm_unit:
2662 decl_in_table = find_decl (REGEXP_UNIT (regexp)->name);
2663 if (decl_in_table == NULL)
2664 error ("undeclared unit or reservation `%s'",
2665 REGEXP_UNIT (regexp)->name);
2666 else
2667 switch (decl_in_table->mode)
2668 {
2669 case dm_unit:
2670 DECL_UNIT (decl_in_table)->unit_is_used = 1;
2671 REGEXP_UNIT (regexp)->unit_decl = DECL_UNIT (decl_in_table);
2672 break;
2673
2674 case dm_reserv:
2675 DECL_RESERV (decl_in_table)->reserv_is_used = 1;
2676 new_regexp = XCREATENODE (struct regexp);
2677 new_regexp->mode = rm_reserv;
2678 new_regexp->pos = regexp->pos;
2679 REGEXP_RESERV (new_regexp)->name = REGEXP_UNIT (regexp)->name;
2680 REGEXP_RESERV (new_regexp)->reserv_decl
2681 = DECL_RESERV (decl_in_table);
2682 regexp = new_regexp;
2683 break;
2684
2685 default:
2686 gcc_unreachable ();
2687 }
2688 break;
2689 case rm_sequence:
2690 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2691 REGEXP_SEQUENCE (regexp)->regexps [i]
2692 = process_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
2693 break;
2694 case rm_allof:
2695 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2696 REGEXP_ALLOF (regexp)->regexps [i]
2697 = process_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
2698 break;
2699 case rm_oneof:
2700 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2701 REGEXP_ONEOF (regexp)->regexps [i]
2702 = process_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
2703 break;
2704 case rm_repeat:
2705 REGEXP_REPEAT (regexp)->regexp
2706 = process_regexp (REGEXP_REPEAT (regexp)->regexp);
2707 break;
2708 case rm_nothing:
2709 break;
2710 default:
2711 gcc_unreachable ();
2712 }
2713 return regexp;
2714 }
2715
2716 /* The following function processes regexp of define_reservation and
2717 define_insn_reservation with the aid of function
2718 `process_regexp'. */
2719 static void
2720 process_regexp_decls (void)
2721 {
2722 decl_t decl;
2723 int i;
2724
2725 for (i = 0; i < description->decls_num; i++)
2726 {
2727 decl = description->decls [i];
2728 if (decl->mode == dm_reserv)
2729 DECL_RESERV (decl)->regexp
2730 = process_regexp (DECL_RESERV (decl)->regexp);
2731 else if (decl->mode == dm_insn_reserv)
2732 DECL_INSN_RESERV (decl)->regexp
2733 = process_regexp (DECL_INSN_RESERV (decl)->regexp);
2734 }
2735 }
2736
2737 /* The following function checks that declared unit is used. If the
2738 unit is not used, the function fixes errors/warnings. The
2739 following function must be called only after `process_decls',
2740 `process_regexp_decls'. */
2741 static void
2742 check_usage (void)
2743 {
2744 decl_t decl;
2745 int i;
2746
2747 for (i = 0; i < description->decls_num; i++)
2748 {
2749 decl = description->decls [i];
2750 if (decl->mode == dm_unit && !DECL_UNIT (decl)->unit_is_used)
2751 {
2752 if (!w_flag)
2753 error ("unit `%s' is not used", DECL_UNIT (decl)->name);
2754 else
2755 warning (0, "unit `%s' is not used", DECL_UNIT (decl)->name);
2756 }
2757 else if (decl->mode == dm_reserv && !DECL_RESERV (decl)->reserv_is_used)
2758 {
2759 if (!w_flag)
2760 error ("reservation `%s' is not used", DECL_RESERV (decl)->name);
2761 else
2762 warning (0, "reservation `%s' is not used", DECL_RESERV (decl)->name);
2763 }
2764 }
2765 }
2766
2767 /* The following variable value is number of reservation being
2768 processed on loop recognition. */
2769 static int curr_loop_pass_num;
2770
2771 /* The following recursive function returns nonzero value if REGEXP
2772 contains given decl or reservations in given regexp refers for
2773 given decl. */
2774 static int
2775 loop_in_regexp (regexp_t regexp, decl_t start_decl)
2776 {
2777 int i;
2778
2779 if (regexp == NULL)
2780 return 0;
2781 switch (regexp->mode)
2782 {
2783 case rm_unit:
2784 return 0;
2785
2786 case rm_reserv:
2787 if (start_decl->mode == dm_reserv
2788 && REGEXP_RESERV (regexp)->reserv_decl == DECL_RESERV (start_decl))
2789 return 1;
2790 else if (REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2791 == curr_loop_pass_num)
2792 /* declaration has been processed. */
2793 return 0;
2794 else
2795 {
2796 REGEXP_RESERV (regexp)->reserv_decl->loop_pass_num
2797 = curr_loop_pass_num;
2798 return loop_in_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2799 start_decl);
2800 }
2801
2802 case rm_sequence:
2803 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2804 if (loop_in_regexp (REGEXP_SEQUENCE (regexp)->regexps [i], start_decl))
2805 return 1;
2806 return 0;
2807
2808 case rm_allof:
2809 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2810 if (loop_in_regexp (REGEXP_ALLOF (regexp)->regexps [i], start_decl))
2811 return 1;
2812 return 0;
2813
2814 case rm_oneof:
2815 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2816 if (loop_in_regexp (REGEXP_ONEOF (regexp)->regexps [i], start_decl))
2817 return 1;
2818 return 0;
2819
2820 case rm_repeat:
2821 return loop_in_regexp (REGEXP_REPEAT (regexp)->regexp, start_decl);
2822
2823 case rm_nothing:
2824 return 0;
2825
2826 default:
2827 gcc_unreachable ();
2828 }
2829 }
2830
2831 /* The following function fixes errors "cycle in definition ...". The
2832 function uses function `loop_in_regexp' for that. */
2833 static void
2834 check_loops_in_regexps (void)
2835 {
2836 decl_t decl;
2837 int i;
2838
2839 for (i = 0; i < description->decls_num; i++)
2840 {
2841 decl = description->decls [i];
2842 if (decl->mode == dm_reserv)
2843 DECL_RESERV (decl)->loop_pass_num = 0;
2844 }
2845 for (i = 0; i < description->decls_num; i++)
2846 {
2847 decl = description->decls [i];
2848 curr_loop_pass_num = i;
2849
2850 if (decl->mode == dm_reserv)
2851 {
2852 DECL_RESERV (decl)->loop_pass_num = curr_loop_pass_num;
2853 if (loop_in_regexp (DECL_RESERV (decl)->regexp, decl))
2854 {
2855 gcc_assert (DECL_RESERV (decl)->regexp);
2856 error ("cycle in definition of reservation `%s'",
2857 DECL_RESERV (decl)->name);
2858 }
2859 }
2860 }
2861 }
2862
2863 /* The function recursively processes IR of reservation and defines
2864 max and min cycle for reservation of unit. */
2865 static void
2866 process_regexp_cycles (regexp_t regexp, int max_start_cycle,
2867 int min_start_cycle, int *max_finish_cycle,
2868 int *min_finish_cycle)
2869 {
2870 int i;
2871
2872 switch (regexp->mode)
2873 {
2874 case rm_unit:
2875 if (REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num < max_start_cycle)
2876 REGEXP_UNIT (regexp)->unit_decl->max_occ_cycle_num = max_start_cycle;
2877 if (REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num > min_start_cycle
2878 || REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num == -1)
2879 REGEXP_UNIT (regexp)->unit_decl->min_occ_cycle_num = min_start_cycle;
2880 *max_finish_cycle = max_start_cycle;
2881 *min_finish_cycle = min_start_cycle;
2882 break;
2883
2884 case rm_reserv:
2885 process_regexp_cycles (REGEXP_RESERV (regexp)->reserv_decl->regexp,
2886 max_start_cycle, min_start_cycle,
2887 max_finish_cycle, min_finish_cycle);
2888 break;
2889
2890 case rm_repeat:
2891 for (i = 0; i < REGEXP_REPEAT (regexp)->repeat_num; i++)
2892 {
2893 process_regexp_cycles (REGEXP_REPEAT (regexp)->regexp,
2894 max_start_cycle, min_start_cycle,
2895 max_finish_cycle, min_finish_cycle);
2896 max_start_cycle = *max_finish_cycle + 1;
2897 min_start_cycle = *min_finish_cycle + 1;
2898 }
2899 break;
2900
2901 case rm_sequence:
2902 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
2903 {
2904 process_regexp_cycles (REGEXP_SEQUENCE (regexp)->regexps [i],
2905 max_start_cycle, min_start_cycle,
2906 max_finish_cycle, min_finish_cycle);
2907 max_start_cycle = *max_finish_cycle + 1;
2908 min_start_cycle = *min_finish_cycle + 1;
2909 }
2910 break;
2911
2912 case rm_allof:
2913 {
2914 int max_cycle = 0;
2915 int min_cycle = 0;
2916
2917 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
2918 {
2919 process_regexp_cycles (REGEXP_ALLOF (regexp)->regexps [i],
2920 max_start_cycle, min_start_cycle,
2921 max_finish_cycle, min_finish_cycle);
2922 if (max_cycle < *max_finish_cycle)
2923 max_cycle = *max_finish_cycle;
2924 if (i == 0 || min_cycle > *min_finish_cycle)
2925 min_cycle = *min_finish_cycle;
2926 }
2927 *max_finish_cycle = max_cycle;
2928 *min_finish_cycle = min_cycle;
2929 }
2930 break;
2931
2932 case rm_oneof:
2933 {
2934 int max_cycle = 0;
2935 int min_cycle = 0;
2936
2937 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
2938 {
2939 process_regexp_cycles (REGEXP_ONEOF (regexp)->regexps [i],
2940 max_start_cycle, min_start_cycle,
2941 max_finish_cycle, min_finish_cycle);
2942 if (max_cycle < *max_finish_cycle)
2943 max_cycle = *max_finish_cycle;
2944 if (i == 0 || min_cycle > *min_finish_cycle)
2945 min_cycle = *min_finish_cycle;
2946 }
2947 *max_finish_cycle = max_cycle;
2948 *min_finish_cycle = min_cycle;
2949 }
2950 break;
2951
2952 case rm_nothing:
2953 *max_finish_cycle = max_start_cycle;
2954 *min_finish_cycle = min_start_cycle;
2955 break;
2956
2957 default:
2958 gcc_unreachable ();
2959 }
2960 }
2961
2962 /* The following function is called only for correct program. The
2963 function defines max reservation of insns in cycles. */
2964 static void
2965 evaluate_max_reserv_cycles (void)
2966 {
2967 int max_insn_cycles_num;
2968 int min_insn_cycles_num;
2969 decl_t decl;
2970 int i;
2971
2972 description->max_insn_reserv_cycles = 0;
2973 for (i = 0; i < description->decls_num; i++)
2974 {
2975 decl = description->decls [i];
2976 if (decl->mode == dm_insn_reserv)
2977 {
2978 process_regexp_cycles (DECL_INSN_RESERV (decl)->regexp, 0, 0,
2979 &max_insn_cycles_num, &min_insn_cycles_num);
2980 if (description->max_insn_reserv_cycles < max_insn_cycles_num)
2981 description->max_insn_reserv_cycles = max_insn_cycles_num;
2982 }
2983 }
2984 description->max_insn_reserv_cycles++;
2985 }
2986
2987 /* The following function calls functions for checking all
2988 description. */
2989 static void
2990 check_all_description (void)
2991 {
2992 process_decls ();
2993 check_automaton_usage ();
2994 process_regexp_decls ();
2995 check_usage ();
2996 check_loops_in_regexps ();
2997 if (!have_error)
2998 evaluate_max_reserv_cycles ();
2999 }
3000
3001
3002
3003 /* The page contains abstract data `ticker'. This data is used to
3004 report time of different phases of building automata. It is
3005 possibly to write a description for which automata will be built
3006 during several minutes even on fast machine. */
3007
3008 /* The following function creates ticker and makes it active. */
3009 static ticker_t
3010 create_ticker (void)
3011 {
3012 ticker_t ticker;
3013
3014 ticker.modified_creation_time = get_run_time ();
3015 ticker.incremented_off_time = 0;
3016 return ticker;
3017 }
3018
3019 /* The following function switches off given ticker. */
3020 static void
3021 ticker_off (ticker_t *ticker)
3022 {
3023 if (ticker->incremented_off_time == 0)
3024 ticker->incremented_off_time = get_run_time () + 1;
3025 }
3026
3027 /* The following function switches on given ticker. */
3028 static void
3029 ticker_on (ticker_t *ticker)
3030 {
3031 if (ticker->incremented_off_time != 0)
3032 {
3033 ticker->modified_creation_time
3034 += get_run_time () - ticker->incremented_off_time + 1;
3035 ticker->incremented_off_time = 0;
3036 }
3037 }
3038
3039 /* The following function returns current time in milliseconds since
3040 the moment when given ticker was created. */
3041 static int
3042 active_time (ticker_t ticker)
3043 {
3044 if (ticker.incremented_off_time != 0)
3045 return ticker.incremented_off_time - 1 - ticker.modified_creation_time;
3046 else
3047 return get_run_time () - ticker.modified_creation_time;
3048 }
3049
3050 /* The following function returns string representation of active time
3051 of given ticker. The result is string representation of seconds
3052 with accuracy of 1/100 second. Only result of the last call of the
3053 function exists. Therefore the following code is not correct
3054
3055 printf ("parser time: %s\ngeneration time: %s\n",
3056 active_time_string (parser_ticker),
3057 active_time_string (generation_ticker));
3058
3059 Correct code has to be the following
3060
3061 printf ("parser time: %s\n", active_time_string (parser_ticker));
3062 printf ("generation time: %s\n",
3063 active_time_string (generation_ticker));
3064
3065 */
3066 static void
3067 print_active_time (FILE *f, ticker_t ticker)
3068 {
3069 int msecs;
3070
3071 msecs = active_time (ticker);
3072 fprintf (f, "%d.%06d", msecs / 1000000, msecs % 1000000);
3073 }
3074
3075
3076
3077 /* The following variable value is number of automaton which are
3078 really being created. This value is defined on the base of
3079 argument of option `-split'. If the variable has zero value the
3080 number of automata is defined by the constructions `%automaton'.
3081 This case occurs when option `-split' is absent or has zero
3082 argument. If constructions `define_automaton' is absent only one
3083 automaton is created. */
3084 static int automata_num;
3085
3086 /* The following variable values are times of
3087 o transformation of regular expressions
3088 o building NDFA (DFA if !ndfa_flag)
3089 o NDFA -> DFA (simply the same automaton if !ndfa_flag)
3090 o DFA minimization
3091 o building insn equivalence classes
3092 o all previous ones
3093 o code output */
3094 static ticker_t transform_time;
3095 static ticker_t NDFA_time;
3096 static ticker_t NDFA_to_DFA_time;
3097 static ticker_t minimize_time;
3098 static ticker_t equiv_time;
3099 static ticker_t automaton_generation_time;
3100 static ticker_t output_time;
3101
3102 /* The following variable values are times of
3103 all checking
3104 all generation
3105 all pipeline hazard translator work */
3106 static ticker_t check_time;
3107 static ticker_t generation_time;
3108 static ticker_t all_time;
3109
3110
3111
3112 /* Pseudo insn decl which denotes advancing cycle. */
3113 static decl_t advance_cycle_insn_decl;
3114 static void
3115 add_advance_cycle_insn_decl (void)
3116 {
3117 advance_cycle_insn_decl = XCREATENODE (struct decl);
3118 advance_cycle_insn_decl->mode = dm_insn_reserv;
3119 advance_cycle_insn_decl->pos = no_pos;
3120 DECL_INSN_RESERV (advance_cycle_insn_decl)->regexp = NULL;
3121 DECL_INSN_RESERV (advance_cycle_insn_decl)->name = "$advance_cycle";
3122 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num
3123 = description->insns_num;
3124 description->decls [description->decls_num] = advance_cycle_insn_decl;
3125 description->decls_num++;
3126 description->insns_num++;
3127 }
3128
3129
3130 /* Abstract data `alternative states' which represents
3131 nondeterministic nature of the description (see comments for
3132 structures alt_state and state). */
3133
3134 /* List of free states. */
3135 static alt_state_t first_free_alt_state;
3136
3137 #ifndef NDEBUG
3138 /* The following variables is maximal number of allocated nodes
3139 alt_state. */
3140 static int allocated_alt_states_num = 0;
3141 #endif
3142
3143 /* The following function returns free node alt_state. It may be new
3144 allocated node or node freed earlier. */
3145 static alt_state_t
3146 get_free_alt_state (void)
3147 {
3148 alt_state_t result;
3149
3150 if (first_free_alt_state != NULL)
3151 {
3152 result = first_free_alt_state;
3153 first_free_alt_state = first_free_alt_state->next_alt_state;
3154 }
3155 else
3156 {
3157 #ifndef NDEBUG
3158 allocated_alt_states_num++;
3159 #endif
3160 result = XCREATENODE (struct alt_state);
3161 }
3162 result->state = NULL;
3163 result->next_alt_state = NULL;
3164 result->next_sorted_alt_state = NULL;
3165 return result;
3166 }
3167
3168 /* The function frees node ALT_STATE. */
3169 static void
3170 free_alt_state (alt_state_t alt_state)
3171 {
3172 if (alt_state == NULL)
3173 return;
3174 alt_state->next_alt_state = first_free_alt_state;
3175 first_free_alt_state = alt_state;
3176 }
3177
3178 /* The function frees list started with node ALT_STATE_LIST. */
3179 static void
3180 free_alt_states (alt_state_t alt_states_list)
3181 {
3182 alt_state_t curr_alt_state;
3183 alt_state_t next_alt_state;
3184
3185 for (curr_alt_state = alt_states_list;
3186 curr_alt_state != NULL;
3187 curr_alt_state = next_alt_state)
3188 {
3189 next_alt_state = curr_alt_state->next_alt_state;
3190 free_alt_state (curr_alt_state);
3191 }
3192 }
3193
3194 /* The function compares unique numbers of alt states. */
3195 static int
3196 alt_state_cmp (const void *alt_state_ptr_1, const void *alt_state_ptr_2)
3197 {
3198 if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3199 == (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3200 return 0;
3201 else if ((*(const alt_state_t *) alt_state_ptr_1)->state->unique_num
3202 < (*(const alt_state_t *) alt_state_ptr_2)->state->unique_num)
3203 return -1;
3204 else
3205 return 1;
3206 }
3207
3208 /* The function sorts ALT_STATES_LIST and removes duplicated alt
3209 states from the list. The comparison key is alt state unique
3210 number. */
3211
3212 static alt_state_t
3213 uniq_sort_alt_states (alt_state_t alt_states_list)
3214 {
3215 alt_state_t curr_alt_state;
3216 VEC(alt_state_t,heap) *alt_states;
3217 size_t i;
3218 size_t prev_unique_state_ind;
3219 alt_state_t result;
3220
3221 if (alt_states_list == 0)
3222 return 0;
3223 if (alt_states_list->next_alt_state == 0)
3224 return alt_states_list;
3225
3226 alt_states = VEC_alloc (alt_state_t,heap, 150);
3227 for (curr_alt_state = alt_states_list;
3228 curr_alt_state != NULL;
3229 curr_alt_state = curr_alt_state->next_alt_state)
3230 VEC_safe_push (alt_state_t,heap, alt_states, curr_alt_state);
3231
3232 qsort (VEC_address (alt_state_t, alt_states),
3233 VEC_length (alt_state_t, alt_states),
3234 sizeof (alt_state_t), alt_state_cmp);
3235
3236 prev_unique_state_ind = 0;
3237 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3238 if (VEC_index (alt_state_t, alt_states, prev_unique_state_ind)->state
3239 != VEC_index (alt_state_t, alt_states, i)->state)
3240 {
3241 prev_unique_state_ind++;
3242 VEC_replace (alt_state_t, alt_states, prev_unique_state_ind,
3243 VEC_index (alt_state_t, alt_states, i));
3244 }
3245 VEC_truncate (alt_state_t, alt_states, prev_unique_state_ind + 1);
3246
3247 for (i = 1; i < VEC_length (alt_state_t, alt_states); i++)
3248 VEC_index (alt_state_t, alt_states, i-1)->next_sorted_alt_state
3249 = VEC_index (alt_state_t, alt_states, i);
3250 VEC_last (alt_state_t, alt_states)->next_sorted_alt_state = 0;
3251
3252 result = VEC_index (alt_state_t, alt_states, 0);
3253
3254 VEC_free (alt_state_t,heap, alt_states);
3255 return result;
3256 }
3257
3258 /* The function checks equality of alt state lists. Remember that the
3259 lists must be already sorted by the previous function. */
3260 static int
3261 alt_states_eq (alt_state_t alt_states_1, alt_state_t alt_states_2)
3262 {
3263 while (alt_states_1 != NULL && alt_states_2 != NULL
3264 && alt_state_cmp (&alt_states_1, &alt_states_2) == 0)
3265 {
3266 alt_states_1 = alt_states_1->next_sorted_alt_state;
3267 alt_states_2 = alt_states_2->next_sorted_alt_state;
3268 }
3269 return alt_states_1 == alt_states_2;
3270 }
3271
3272 /* Initialization of the abstract data. */
3273 static void
3274 initiate_alt_states (void)
3275 {
3276 first_free_alt_state = NULL;
3277 }
3278
3279 /* Finishing work with the abstract data. */
3280 static void
3281 finish_alt_states (void)
3282 {
3283 }
3284
3285
3286
3287 /* The page contains macros for work with bits strings. We could use
3288 standard gcc bitmap or sbitmap but it would result in difficulties
3289 of building canadian cross. */
3290
3291 /* Set bit number bitno in the bit string. The macro is not side
3292 effect proof. */
3293 #define SET_BIT(bitstring, bitno) \
3294 (((char *) (bitstring)) [(bitno) / CHAR_BIT] |= 1 << (bitno) % CHAR_BIT)
3295
3296 #define CLEAR_BIT(bitstring, bitno) \
3297 (((char *) (bitstring)) [(bitno) / CHAR_BIT] &= ~(1 << (bitno) % CHAR_BIT))
3298
3299 /* Test if bit number bitno in the bitstring is set. The macro is not
3300 side effect proof. */
3301 #define TEST_BIT(bitstring, bitno) \
3302 (((char *) (bitstring)) [(bitno) / CHAR_BIT] >> (bitno) % CHAR_BIT & 1)
3303
3304
3305
3306 /* This page contains abstract data `state'. */
3307
3308 /* Maximal length of reservations in cycles (>= 1). */
3309 static int max_cycles_num;
3310
3311 /* Number of set elements (see type set_el_t) needed for
3312 representation of one cycle reservation. It is depended on units
3313 number. */
3314 static int els_in_cycle_reserv;
3315
3316 /* Number of set elements (see type set_el_t) needed for
3317 representation of maximal length reservation. Deterministic
3318 reservation is stored as set (bit string) of length equal to the
3319 variable value * number of bits in set_el_t. */
3320 static int els_in_reservs;
3321
3322 /* Array of pointers to unit declarations. */
3323 static unit_decl_t *units_array;
3324
3325 /* Temporary reservation of maximal length. */
3326 static reserv_sets_t temp_reserv;
3327
3328 /* The state table itself is represented by the following variable. */
3329 static htab_t state_table;
3330
3331 /* Linked list of free 'state' structures to be recycled. The
3332 next_equiv_class_state pointer is borrowed for a free list. */
3333 static state_t first_free_state;
3334
3335 static int curr_unique_state_num;
3336
3337 #ifndef NDEBUG
3338 /* The following variables is maximal number of allocated nodes
3339 `state'. */
3340 static int allocated_states_num = 0;
3341 #endif
3342
3343 /* Allocate new reservation set. */
3344 static reserv_sets_t
3345 alloc_empty_reserv_sets (void)
3346 {
3347 reserv_sets_t result;
3348
3349 obstack_blank (&irp, els_in_reservs * sizeof (set_el_t));
3350 result = (reserv_sets_t) obstack_base (&irp);
3351 obstack_finish (&irp);
3352 memset (result, 0, els_in_reservs * sizeof (set_el_t));
3353 return result;
3354 }
3355
3356 /* Hash value of reservation set. */
3357 static unsigned
3358 reserv_sets_hash_value (reserv_sets_t reservs)
3359 {
3360 set_el_t hash_value;
3361 unsigned result;
3362 int reservs_num, i;
3363 set_el_t *reserv_ptr;
3364
3365 hash_value = 0;
3366 reservs_num = els_in_reservs;
3367 reserv_ptr = reservs;
3368 i = 0;
3369 while (reservs_num != 0)
3370 {
3371 reservs_num--;
3372 hash_value += ((*reserv_ptr >> i)
3373 | (*reserv_ptr << (sizeof (set_el_t) * CHAR_BIT - i)));
3374 i++;
3375 if (i == sizeof (set_el_t) * CHAR_BIT)
3376 i = 0;
3377 reserv_ptr++;
3378 }
3379 if (sizeof (set_el_t) <= sizeof (unsigned))
3380 return hash_value;
3381 result = 0;
3382 for (i = sizeof (set_el_t); i > 0; i -= sizeof (unsigned) - 1)
3383 {
3384 result += (unsigned) hash_value;
3385 hash_value >>= (sizeof (unsigned) - 1) * CHAR_BIT;
3386 }
3387 return result;
3388 }
3389
3390 /* Comparison of given reservation sets. */
3391 static int
3392 reserv_sets_cmp (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3393 {
3394 int reservs_num;
3395 const set_el_t *reserv_ptr_1;
3396 const set_el_t *reserv_ptr_2;
3397
3398 gcc_assert (reservs_1 && reservs_2);
3399 reservs_num = els_in_reservs;
3400 reserv_ptr_1 = reservs_1;
3401 reserv_ptr_2 = reservs_2;
3402 while (reservs_num != 0 && *reserv_ptr_1 == *reserv_ptr_2)
3403 {
3404 reservs_num--;
3405 reserv_ptr_1++;
3406 reserv_ptr_2++;
3407 }
3408 if (reservs_num == 0)
3409 return 0;
3410 else if (*reserv_ptr_1 < *reserv_ptr_2)
3411 return -1;
3412 else
3413 return 1;
3414 }
3415
3416 /* The function checks equality of the reservation sets. */
3417 static int
3418 reserv_sets_eq (const_reserv_sets_t reservs_1, const_reserv_sets_t reservs_2)
3419 {
3420 return reserv_sets_cmp (reservs_1, reservs_2) == 0;
3421 }
3422
3423 /* Set up in the reservation set that unit with UNIT_NUM is used on
3424 CYCLE_NUM. */
3425 static void
3426 set_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3427 {
3428 gcc_assert (cycle_num < max_cycles_num);
3429 SET_BIT (reservs, cycle_num * els_in_cycle_reserv
3430 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3431 }
3432
3433 /* Set up in the reservation set RESERVS that unit with UNIT_NUM is
3434 used on CYCLE_NUM. */
3435 static int
3436 test_unit_reserv (reserv_sets_t reservs, int cycle_num, int unit_num)
3437 {
3438 gcc_assert (cycle_num < max_cycles_num);
3439 return TEST_BIT (reservs, cycle_num * els_in_cycle_reserv
3440 * sizeof (set_el_t) * CHAR_BIT + unit_num);
3441 }
3442
3443 /* The function checks that the reservation sets are intersected,
3444 i.e. there is a unit reservation on a cycle in both reservation
3445 sets. */
3446 static int
3447 reserv_sets_are_intersected (reserv_sets_t operand_1,
3448 reserv_sets_t operand_2)
3449 {
3450 set_el_t *el_ptr_1;
3451 set_el_t *el_ptr_2;
3452 set_el_t *cycle_ptr_1;
3453 set_el_t *cycle_ptr_2;
3454
3455 gcc_assert (operand_1 && operand_2);
3456 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2;
3457 el_ptr_1 < operand_1 + els_in_reservs;
3458 el_ptr_1++, el_ptr_2++)
3459 if (*el_ptr_1 & *el_ptr_2)
3460 return 1;
3461 reserv_sets_or (temp_reserv, operand_1, operand_2);
3462 for (cycle_ptr_1 = operand_1, cycle_ptr_2 = operand_2;
3463 cycle_ptr_1 < operand_1 + els_in_reservs;
3464 cycle_ptr_1 += els_in_cycle_reserv, cycle_ptr_2 += els_in_cycle_reserv)
3465 {
3466 for (el_ptr_1 = cycle_ptr_1, el_ptr_2 = get_excl_set (cycle_ptr_2);
3467 el_ptr_1 < cycle_ptr_1 + els_in_cycle_reserv;
3468 el_ptr_1++, el_ptr_2++)
3469 if (*el_ptr_1 & *el_ptr_2)
3470 return 1;
3471 if (!check_presence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3472 return 1;
3473 if (!check_presence_pattern_sets (temp_reserv + (cycle_ptr_2
3474 - operand_2),
3475 cycle_ptr_2, TRUE))
3476 return 1;
3477 if (!check_absence_pattern_sets (cycle_ptr_1, cycle_ptr_2, FALSE))
3478 return 1;
3479 if (!check_absence_pattern_sets (temp_reserv + (cycle_ptr_2 - operand_2),
3480 cycle_ptr_2, TRUE))
3481 return 1;
3482 }
3483 return 0;
3484 }
3485
3486 /* The function sets up RESULT bits by bits of OPERAND shifted on one
3487 cpu cycle. The remaining bits of OPERAND (representing the last
3488 cycle unit reservations) are not changed. */
3489 static void
3490 reserv_sets_shift (reserv_sets_t result, reserv_sets_t operand)
3491 {
3492 int i;
3493
3494 gcc_assert (result && operand && result != operand);
3495 for (i = els_in_cycle_reserv; i < els_in_reservs; i++)
3496 result [i - els_in_cycle_reserv] = operand [i];
3497 }
3498
3499 /* OR of the reservation sets. */
3500 static void
3501 reserv_sets_or (reserv_sets_t result, reserv_sets_t operand_1,
3502 reserv_sets_t operand_2)
3503 {
3504 set_el_t *el_ptr_1;
3505 set_el_t *el_ptr_2;
3506 set_el_t *result_set_el_ptr;
3507
3508 gcc_assert (result && operand_1 && operand_2);
3509 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3510 el_ptr_1 < operand_1 + els_in_reservs;
3511 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3512 *result_set_el_ptr = *el_ptr_1 | *el_ptr_2;
3513 }
3514
3515 /* AND of the reservation sets. */
3516 static void
3517 reserv_sets_and (reserv_sets_t result, reserv_sets_t operand_1,
3518 reserv_sets_t operand_2)
3519 {
3520 set_el_t *el_ptr_1;
3521 set_el_t *el_ptr_2;
3522 set_el_t *result_set_el_ptr;
3523
3524 gcc_assert (result && operand_1 && operand_2);
3525 for (el_ptr_1 = operand_1, el_ptr_2 = operand_2, result_set_el_ptr = result;
3526 el_ptr_1 < operand_1 + els_in_reservs;
3527 el_ptr_1++, el_ptr_2++, result_set_el_ptr++)
3528 *result_set_el_ptr = *el_ptr_1 & *el_ptr_2;
3529 }
3530
3531 /* The function outputs string representation of units reservation on
3532 cycle START_CYCLE in the reservation set. The function uses repeat
3533 construction if REPETITION_NUM > 1. */
3534 static void
3535 output_cycle_reservs (FILE *f, reserv_sets_t reservs, int start_cycle,
3536 int repetition_num)
3537 {
3538 int unit_num;
3539 int reserved_units_num;
3540
3541 reserved_units_num = 0;
3542 for (unit_num = 0; unit_num < description->units_num; unit_num++)
3543 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3544 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3545 reserved_units_num++;
3546 gcc_assert (repetition_num > 0);
3547 if (repetition_num != 1 && reserved_units_num > 1)
3548 fprintf (f, "(");
3549 reserved_units_num = 0;
3550 for (unit_num = 0;
3551 unit_num < description->units_num;
3552 unit_num++)
3553 if (TEST_BIT (reservs, start_cycle * els_in_cycle_reserv
3554 * sizeof (set_el_t) * CHAR_BIT + unit_num))
3555 {
3556 if (reserved_units_num != 0)
3557 fprintf (f, "+");
3558 reserved_units_num++;
3559 fprintf (f, "%s", units_array [unit_num]->name);
3560 }
3561 if (reserved_units_num == 0)
3562 fprintf (f, NOTHING_NAME);
3563 gcc_assert (repetition_num > 0);
3564 if (repetition_num != 1 && reserved_units_num > 1)
3565 fprintf (f, ")");
3566 if (repetition_num != 1)
3567 fprintf (f, "*%d", repetition_num);
3568 }
3569
3570 /* The function outputs string representation of units reservation in
3571 the reservation set. */
3572 static void
3573 output_reserv_sets (FILE *f, reserv_sets_t reservs)
3574 {
3575 int start_cycle = 0;
3576 int cycle;
3577 int repetition_num;
3578
3579 repetition_num = 0;
3580 for (cycle = 0; cycle < max_cycles_num; cycle++)
3581 if (repetition_num == 0)
3582 {
3583 repetition_num++;
3584 start_cycle = cycle;
3585 }
3586 else if (memcmp
3587 ((char *) reservs + start_cycle * els_in_cycle_reserv
3588 * sizeof (set_el_t),
3589 (char *) reservs + cycle * els_in_cycle_reserv
3590 * sizeof (set_el_t),
3591 els_in_cycle_reserv * sizeof (set_el_t)) == 0)
3592 repetition_num++;
3593 else
3594 {
3595 if (start_cycle != 0)
3596 fprintf (f, ", ");
3597 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3598 repetition_num = 1;
3599 start_cycle = cycle;
3600 }
3601 if (start_cycle < max_cycles_num)
3602 {
3603 if (start_cycle != 0)
3604 fprintf (f, ", ");
3605 output_cycle_reservs (f, reservs, start_cycle, repetition_num);
3606 }
3607 }
3608
3609 /* The following function returns free node state for AUTOMATON. It
3610 may be new allocated node or node freed earlier. The function also
3611 allocates reservation set if WITH_RESERVS has nonzero value. */
3612 static state_t
3613 get_free_state (int with_reservs, automaton_t automaton)
3614 {
3615 state_t result;
3616
3617 gcc_assert (max_cycles_num > 0 && automaton);
3618 if (first_free_state)
3619 {
3620 result = first_free_state;
3621 first_free_state = result->next_equiv_class_state;
3622
3623 result->next_equiv_class_state = NULL;
3624 result->automaton = automaton;
3625 result->first_out_arc = NULL;
3626 result->it_was_placed_in_stack_for_NDFA_forming = 0;
3627 result->it_was_placed_in_stack_for_DFA_forming = 0;
3628 result->component_states = NULL;
3629 }
3630 else
3631 {
3632 #ifndef NDEBUG
3633 allocated_states_num++;
3634 #endif
3635 result = XCREATENODE (struct state);
3636 result->automaton = automaton;
3637 result->first_out_arc = NULL;
3638 result->unique_num = curr_unique_state_num;
3639 curr_unique_state_num++;
3640 }
3641 if (with_reservs)
3642 {
3643 if (result->reservs == NULL)
3644 result->reservs = alloc_empty_reserv_sets ();
3645 else
3646 memset (result->reservs, 0, els_in_reservs * sizeof (set_el_t));
3647 }
3648 return result;
3649 }
3650
3651 /* The function frees node STATE. */
3652 static void
3653 free_state (state_t state)
3654 {
3655 free_alt_states (state->component_states);
3656 state->next_equiv_class_state = first_free_state;
3657 first_free_state = state;
3658 }
3659
3660 /* Hash value of STATE. If STATE represents deterministic state it is
3661 simply hash value of the corresponding reservation set. Otherwise
3662 it is formed from hash values of the component deterministic
3663 states. One more key is order number of state automaton. */
3664 static hashval_t
3665 state_hash (const void *state)
3666 {
3667 unsigned int hash_value;
3668 alt_state_t alt_state;
3669
3670 if (((const_state_t) state)->component_states == NULL)
3671 hash_value = reserv_sets_hash_value (((const_state_t) state)->reservs);
3672 else
3673 {
3674 hash_value = 0;
3675 for (alt_state = ((const_state_t) state)->component_states;
3676 alt_state != NULL;
3677 alt_state = alt_state->next_sorted_alt_state)
3678 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3679 | (hash_value << CHAR_BIT))
3680 + alt_state->state->unique_num);
3681 }
3682 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
3683 | (hash_value << CHAR_BIT))
3684 + ((const_state_t) state)->automaton->automaton_order_num);
3685 return hash_value;
3686 }
3687
3688 /* Return nonzero value if the states are the same. */
3689 static int
3690 state_eq_p (const void *state_1, const void *state_2)
3691 {
3692 alt_state_t alt_state_1;
3693 alt_state_t alt_state_2;
3694
3695 if (((const_state_t) state_1)->automaton != ((const_state_t) state_2)->automaton)
3696 return 0;
3697 else if (((const_state_t) state_1)->component_states == NULL
3698 && ((const_state_t) state_2)->component_states == NULL)
3699 return reserv_sets_eq (((const_state_t) state_1)->reservs,
3700 ((const_state_t) state_2)->reservs);
3701 else if (((const_state_t) state_1)->component_states != NULL
3702 && ((const_state_t) state_2)->component_states != NULL)
3703 {
3704 for (alt_state_1 = ((const_state_t) state_1)->component_states,
3705 alt_state_2 = ((const_state_t) state_2)->component_states;
3706 alt_state_1 != NULL && alt_state_2 != NULL;
3707 alt_state_1 = alt_state_1->next_sorted_alt_state,
3708 alt_state_2 = alt_state_2->next_sorted_alt_state)
3709 /* All state in the list must be already in the hash table.
3710 Also the lists must be sorted. */
3711 if (alt_state_1->state != alt_state_2->state)
3712 return 0;
3713 return alt_state_1 == alt_state_2;
3714 }
3715 else
3716 return 0;
3717 }
3718
3719 /* Insert STATE into the state table. */
3720 static state_t
3721 insert_state (state_t state)
3722 {
3723 void **entry_ptr;
3724
3725 entry_ptr = htab_find_slot (state_table, (void *) state, 1);
3726 if (*entry_ptr == NULL)
3727 *entry_ptr = (void *) state;
3728 return (state_t) *entry_ptr;
3729 }
3730
3731 /* Add reservation of unit with UNIT_NUM on cycle CYCLE_NUM to
3732 deterministic STATE. */
3733 static void
3734 set_state_reserv (state_t state, int cycle_num, int unit_num)
3735 {
3736 set_unit_reserv (state->reservs, cycle_num, unit_num);
3737 }
3738
3739 /* Return nonzero value if the deterministic states contains a
3740 reservation of the same cpu unit on the same cpu cycle. */
3741 static int
3742 intersected_state_reservs_p (state_t state1, state_t state2)
3743 {
3744 gcc_assert (state1->automaton == state2->automaton);
3745 return reserv_sets_are_intersected (state1->reservs, state2->reservs);
3746 }
3747
3748 /* Return deterministic state (inserted into the table) which
3749 representing the automaton state which is union of reservations of
3750 the deterministic states masked by RESERVS. */
3751 static state_t
3752 states_union (state_t state1, state_t state2, reserv_sets_t reservs)
3753 {
3754 state_t result;
3755 state_t state_in_table;
3756
3757 gcc_assert (state1->automaton == state2->automaton);
3758 result = get_free_state (1, state1->automaton);
3759 reserv_sets_or (result->reservs, state1->reservs, state2->reservs);
3760 reserv_sets_and (result->reservs, result->reservs, reservs);
3761 state_in_table = insert_state (result);
3762 if (result != state_in_table)
3763 {
3764 free_state (result);
3765 result = state_in_table;
3766 }
3767 return result;
3768 }
3769
3770 /* Return deterministic state (inserted into the table) which
3771 represent the automaton state is obtained from deterministic STATE
3772 by advancing cpu cycle and masking by RESERVS. */
3773 static state_t
3774 state_shift (state_t state, reserv_sets_t reservs)
3775 {
3776 state_t result;
3777 state_t state_in_table;
3778
3779 result = get_free_state (1, state->automaton);
3780 reserv_sets_shift (result->reservs, state->reservs);
3781 reserv_sets_and (result->reservs, result->reservs, reservs);
3782 state_in_table = insert_state (result);
3783 if (result != state_in_table)
3784 {
3785 free_state (result);
3786 result = state_in_table;
3787 }
3788 return result;
3789 }
3790
3791 /* Initialization of the abstract data. */
3792 static void
3793 initiate_states (void)
3794 {
3795 decl_t decl;
3796 int i;
3797
3798 if (description->units_num)
3799 units_array = XNEWVEC (unit_decl_t, description->units_num);
3800 else
3801 units_array = 0;
3802
3803 for (i = 0; i < description->decls_num; i++)
3804 {
3805 decl = description->decls [i];
3806 if (decl->mode == dm_unit)
3807 units_array [DECL_UNIT (decl)->unit_num] = DECL_UNIT (decl);
3808 }
3809 max_cycles_num = description->max_insn_reserv_cycles;
3810 els_in_cycle_reserv
3811 = ((description->units_num + sizeof (set_el_t) * CHAR_BIT - 1)
3812 / (sizeof (set_el_t) * CHAR_BIT));
3813 els_in_reservs = els_in_cycle_reserv * max_cycles_num;
3814 curr_unique_state_num = 0;
3815 initiate_alt_states ();
3816 state_table = htab_create (1500, state_hash, state_eq_p, (htab_del) 0);
3817 temp_reserv = alloc_empty_reserv_sets ();
3818 }
3819
3820 /* Finishing work with the abstract data. */
3821 static void
3822 finish_states (void)
3823 {
3824 free (units_array);
3825 units_array = 0;
3826 htab_delete (state_table);
3827 first_free_state = NULL;
3828 finish_alt_states ();
3829 }
3830
3831
3832
3833 /* Abstract data `arcs'. */
3834
3835 /* List of free arcs. */
3836 static arc_t first_free_arc;
3837
3838 #ifndef NDEBUG
3839 /* The following variables is maximal number of allocated nodes
3840 `arc'. */
3841 static int allocated_arcs_num = 0;
3842 #endif
3843
3844 /* The function frees node ARC. */
3845 static void
3846 free_arc (arc_t arc)
3847 {
3848 arc->next_out_arc = first_free_arc;
3849 first_free_arc = arc;
3850 }
3851
3852 /* The function removes and frees ARC staring from FROM_STATE. */
3853 static void
3854 remove_arc (state_t from_state, arc_t arc)
3855 {
3856 arc_t prev_arc;
3857 arc_t curr_arc;
3858
3859 gcc_assert (arc);
3860 for (prev_arc = NULL, curr_arc = from_state->first_out_arc;
3861 curr_arc != NULL;
3862 prev_arc = curr_arc, curr_arc = curr_arc->next_out_arc)
3863 if (curr_arc == arc)
3864 break;
3865 gcc_assert (curr_arc);
3866 if (prev_arc == NULL)
3867 from_state->first_out_arc = arc->next_out_arc;
3868 else
3869 prev_arc->next_out_arc = arc->next_out_arc;
3870 from_state->num_out_arcs--;
3871 free_arc (arc);
3872 }
3873
3874 /* The functions returns arc with given characteristics (or NULL if
3875 the arc does not exist). */
3876 static arc_t
3877 find_arc (state_t from_state, state_t to_state, ainsn_t insn)
3878 {
3879 arc_t arc;
3880
3881 for (arc = first_out_arc (from_state); arc != NULL; arc = next_out_arc (arc))
3882 if (arc->to_state == to_state && arc->insn == insn)
3883 return arc;
3884 return NULL;
3885 }
3886
3887 /* The function adds arc from FROM_STATE to TO_STATE marked by AINSN.
3888 The function returns added arc (or already existing arc). */
3889 static arc_t
3890 add_arc (state_t from_state, state_t to_state, ainsn_t ainsn)
3891 {
3892 arc_t new_arc;
3893
3894 new_arc = find_arc (from_state, to_state, ainsn);
3895 if (new_arc != NULL)
3896 return new_arc;
3897 if (first_free_arc == NULL)
3898 {
3899 #ifndef NDEBUG
3900 allocated_arcs_num++;
3901 #endif
3902 new_arc = XCREATENODE (struct arc);
3903 new_arc->to_state = NULL;
3904 new_arc->insn = NULL;
3905 new_arc->next_out_arc = NULL;
3906 }
3907 else
3908 {
3909 new_arc = first_free_arc;
3910 first_free_arc = first_free_arc->next_out_arc;
3911 }
3912 new_arc->to_state = to_state;
3913 new_arc->insn = ainsn;
3914 ainsn->arc_exists_p = 1;
3915 new_arc->next_out_arc = from_state->first_out_arc;
3916 from_state->first_out_arc = new_arc;
3917 from_state->num_out_arcs++;
3918 new_arc->next_arc_marked_by_insn = NULL;
3919 return new_arc;
3920 }
3921
3922 /* The function returns the first arc starting from STATE. */
3923 static arc_t
3924 first_out_arc (const_state_t state)
3925 {
3926 return state->first_out_arc;
3927 }
3928
3929 /* The function returns next out arc after ARC. */
3930 static arc_t
3931 next_out_arc (arc_t arc)
3932 {
3933 return arc->next_out_arc;
3934 }
3935
3936 /* Initialization of the abstract data. */
3937 static void
3938 initiate_arcs (void)
3939 {
3940 first_free_arc = NULL;
3941 }
3942
3943 /* Finishing work with the abstract data. */
3944 static void
3945 finish_arcs (void)
3946 {
3947 }
3948
3949
3950
3951 /* Abstract data `automata lists'. */
3952
3953 /* List of free states. */
3954 static automata_list_el_t first_free_automata_list_el;
3955
3956 /* The list being formed. */
3957 static automata_list_el_t current_automata_list;
3958
3959 /* Hash table of automata lists. */
3960 static htab_t automata_list_table;
3961
3962 /* The following function returns free automata list el. It may be
3963 new allocated node or node freed earlier. */
3964 static automata_list_el_t
3965 get_free_automata_list_el (void)
3966 {
3967 automata_list_el_t result;
3968
3969 if (first_free_automata_list_el != NULL)
3970 {
3971 result = first_free_automata_list_el;
3972 first_free_automata_list_el
3973 = first_free_automata_list_el->next_automata_list_el;
3974 }
3975 else
3976 result = XCREATENODE (struct automata_list_el);
3977 result->automaton = NULL;
3978 result->next_automata_list_el = NULL;
3979 return result;
3980 }
3981
3982 /* The function frees node AUTOMATA_LIST_EL. */
3983 static void
3984 free_automata_list_el (automata_list_el_t automata_list_el)
3985 {
3986 if (automata_list_el == NULL)
3987 return;
3988 automata_list_el->next_automata_list_el = first_free_automata_list_el;
3989 first_free_automata_list_el = automata_list_el;
3990 }
3991
3992 /* The function frees list AUTOMATA_LIST. */
3993 static void
3994 free_automata_list (automata_list_el_t automata_list)
3995 {
3996 automata_list_el_t curr_automata_list_el;
3997 automata_list_el_t next_automata_list_el;
3998
3999 for (curr_automata_list_el = automata_list;
4000 curr_automata_list_el != NULL;
4001 curr_automata_list_el = next_automata_list_el)
4002 {
4003 next_automata_list_el = curr_automata_list_el->next_automata_list_el;
4004 free_automata_list_el (curr_automata_list_el);
4005 }
4006 }
4007
4008 /* Hash value of AUTOMATA_LIST. */
4009 static hashval_t
4010 automata_list_hash (const void *automata_list)
4011 {
4012 unsigned int hash_value;
4013 const_automata_list_el_t curr_automata_list_el;
4014
4015 hash_value = 0;
4016 for (curr_automata_list_el = (const_automata_list_el_t) automata_list;
4017 curr_automata_list_el != NULL;
4018 curr_automata_list_el = curr_automata_list_el->next_automata_list_el)
4019 hash_value = (((hash_value >> (sizeof (unsigned) - 1) * CHAR_BIT)
4020 | (hash_value << CHAR_BIT))
4021 + curr_automata_list_el->automaton->automaton_order_num);
4022 return hash_value;
4023 }
4024
4025 /* Return nonzero value if the automata_lists are the same. */
4026 static int
4027 automata_list_eq_p (const void *automata_list_1, const void *automata_list_2)
4028 {
4029 const_automata_list_el_t automata_list_el_1;
4030 const_automata_list_el_t automata_list_el_2;
4031
4032 for (automata_list_el_1 = (const_automata_list_el_t) automata_list_1,
4033 automata_list_el_2 = (const_automata_list_el_t) automata_list_2;
4034 automata_list_el_1 != NULL && automata_list_el_2 != NULL;
4035 automata_list_el_1 = automata_list_el_1->next_automata_list_el,
4036 automata_list_el_2 = automata_list_el_2->next_automata_list_el)
4037 if (automata_list_el_1->automaton != automata_list_el_2->automaton)
4038 return 0;
4039 return automata_list_el_1 == automata_list_el_2;
4040 }
4041
4042 /* Initialization of the abstract data. */
4043 static void
4044 initiate_automata_lists (void)
4045 {
4046 first_free_automata_list_el = NULL;
4047 automata_list_table = htab_create (1500, automata_list_hash,
4048 automata_list_eq_p, (htab_del) 0);
4049 }
4050
4051 /* The following function starts new automata list and makes it the
4052 current one. */
4053 static void
4054 automata_list_start (void)
4055 {
4056 current_automata_list = NULL;
4057 }
4058
4059 /* The following function adds AUTOMATON to the current list. */
4060 static void
4061 automata_list_add (automaton_t automaton)
4062 {
4063 automata_list_el_t el;
4064
4065 el = get_free_automata_list_el ();
4066 el->automaton = automaton;
4067 el->next_automata_list_el = current_automata_list;
4068 current_automata_list = el;
4069 }
4070
4071 /* The following function finishes forming the current list, inserts
4072 it into the table and returns it. */
4073 static automata_list_el_t
4074 automata_list_finish (void)
4075 {
4076 void **entry_ptr;
4077
4078 if (current_automata_list == NULL)
4079 return NULL;
4080 entry_ptr = htab_find_slot (automata_list_table,
4081 (void *) current_automata_list, 1);
4082 if (*entry_ptr == NULL)
4083 *entry_ptr = (void *) current_automata_list;
4084 else
4085 free_automata_list (current_automata_list);
4086 current_automata_list = NULL;
4087 return (automata_list_el_t) *entry_ptr;
4088 }
4089
4090 /* Finishing work with the abstract data. */
4091 static void
4092 finish_automata_lists (void)
4093 {
4094 htab_delete (automata_list_table);
4095 }
4096
4097
4098
4099 /* The page contains abstract data for work with exclusion sets (see
4100 exclusion_set in file rtl.def). */
4101
4102 /* The following variable refers to an exclusion set returned by
4103 get_excl_set. This is bit string of length equal to cpu units
4104 number. If exclusion set for given unit contains 1 for a unit,
4105 then simultaneous reservation of the units is prohibited. */
4106 static reserv_sets_t excl_set;
4107
4108 /* The array contains exclusion sets for each unit. */
4109 static reserv_sets_t *unit_excl_set_table;
4110
4111 /* The following function forms the array containing exclusion sets
4112 for each unit. */
4113 static void
4114 initiate_excl_sets (void)
4115 {
4116 decl_t decl;
4117 reserv_sets_t unit_excl_set;
4118 unit_set_el_t el;
4119 int i;
4120
4121 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4122 excl_set = (reserv_sets_t) obstack_base (&irp);
4123 obstack_finish (&irp);
4124 obstack_blank (&irp, description->units_num * sizeof (reserv_sets_t));
4125 unit_excl_set_table = (reserv_sets_t *) obstack_base (&irp);
4126 obstack_finish (&irp);
4127 /* Evaluate unit exclusion sets. */
4128 for (i = 0; i < description->decls_num; i++)
4129 {
4130 decl = description->decls [i];
4131 if (decl->mode == dm_unit)
4132 {
4133 obstack_blank (&irp, els_in_cycle_reserv * sizeof (set_el_t));
4134 unit_excl_set = (reserv_sets_t) obstack_base (&irp);
4135 obstack_finish (&irp);
4136 memset (unit_excl_set, 0, els_in_cycle_reserv * sizeof (set_el_t));
4137 for (el = DECL_UNIT (decl)->excl_list;
4138 el != NULL;
4139 el = el->next_unit_set_el)
4140 {
4141 SET_BIT (unit_excl_set, el->unit_decl->unit_num);
4142 el->unit_decl->in_set_p = TRUE;
4143 }
4144 unit_excl_set_table [DECL_UNIT (decl)->unit_num] = unit_excl_set;
4145 }
4146 }
4147 }
4148
4149 /* The function sets up and return EXCL_SET which is union of
4150 exclusion sets for each unit in IN_SET. */
4151 static reserv_sets_t
4152 get_excl_set (reserv_sets_t in_set)
4153 {
4154 int excl_char_num;
4155 int chars_num;
4156 int i;
4157 int start_unit_num;
4158 int unit_num;
4159
4160 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4161 memset (excl_set, 0, chars_num);
4162 for (excl_char_num = 0; excl_char_num < chars_num; excl_char_num++)
4163 if (((unsigned char *) in_set) [excl_char_num])
4164 for (i = CHAR_BIT - 1; i >= 0; i--)
4165 if ((((unsigned char *) in_set) [excl_char_num] >> i) & 1)
4166 {
4167 start_unit_num = excl_char_num * CHAR_BIT + i;
4168 if (start_unit_num >= description->units_num)
4169 return excl_set;
4170 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4171 {
4172 excl_set [unit_num]
4173 |= unit_excl_set_table [start_unit_num] [unit_num];
4174 }
4175 }
4176 return excl_set;
4177 }
4178
4179
4180
4181 /* The page contains abstract data for work with presence/absence
4182 pattern sets (see presence_set/absence_set in file rtl.def). */
4183
4184 /* The following arrays contain correspondingly presence, final
4185 presence, absence, and final absence patterns for each unit. */
4186 static pattern_reserv_t *unit_presence_set_table;
4187 static pattern_reserv_t *unit_final_presence_set_table;
4188 static pattern_reserv_t *unit_absence_set_table;
4189 static pattern_reserv_t *unit_final_absence_set_table;
4190
4191 /* The following function forms list of reservation sets for given
4192 PATTERN_LIST. */
4193 static pattern_reserv_t
4194 form_reserv_sets_list (pattern_set_el_t pattern_list)
4195 {
4196 pattern_set_el_t el;
4197 pattern_reserv_t first, curr, prev;
4198 int i;
4199
4200 prev = first = NULL;
4201 for (el = pattern_list; el != NULL; el = el->next_pattern_set_el)
4202 {
4203 curr = XCREATENODE (struct pattern_reserv);
4204 curr->reserv = alloc_empty_reserv_sets ();
4205 curr->next_pattern_reserv = NULL;
4206 for (i = 0; i < el->units_num; i++)
4207 {
4208 SET_BIT (curr->reserv, el->unit_decls [i]->unit_num);
4209 el->unit_decls [i]->in_set_p = TRUE;
4210 }
4211 if (prev != NULL)
4212 prev->next_pattern_reserv = curr;
4213 else
4214 first = curr;
4215 prev = curr;
4216 }
4217 return first;
4218 }
4219
4220 /* The following function forms the array containing presence and
4221 absence pattern sets for each unit. */
4222 static void
4223 initiate_presence_absence_pattern_sets (void)
4224 {
4225 decl_t decl;
4226 int i;
4227
4228 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4229 unit_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4230 obstack_finish (&irp);
4231 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4232 unit_final_presence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4233 obstack_finish (&irp);
4234 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4235 unit_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4236 obstack_finish (&irp);
4237 obstack_blank (&irp, description->units_num * sizeof (pattern_reserv_t));
4238 unit_final_absence_set_table = (pattern_reserv_t *) obstack_base (&irp);
4239 obstack_finish (&irp);
4240 /* Evaluate unit presence/absence sets. */
4241 for (i = 0; i < description->decls_num; i++)
4242 {
4243 decl = description->decls [i];
4244 if (decl->mode == dm_unit)
4245 {
4246 unit_presence_set_table [DECL_UNIT (decl)->unit_num]
4247 = form_reserv_sets_list (DECL_UNIT (decl)->presence_list);
4248 unit_final_presence_set_table [DECL_UNIT (decl)->unit_num]
4249 = form_reserv_sets_list (DECL_UNIT (decl)->final_presence_list);
4250 unit_absence_set_table [DECL_UNIT (decl)->unit_num]
4251 = form_reserv_sets_list (DECL_UNIT (decl)->absence_list);
4252 unit_final_absence_set_table [DECL_UNIT (decl)->unit_num]
4253 = form_reserv_sets_list (DECL_UNIT (decl)->final_absence_list);
4254 }
4255 }
4256 }
4257
4258 /* The function checks that CHECKED_SET satisfies all presence pattern
4259 sets for units in ORIGINAL_SET. The function returns TRUE if it
4260 is ok. */
4261 static int
4262 check_presence_pattern_sets (reserv_sets_t checked_set,
4263 reserv_sets_t original_set,
4264 int final_p)
4265 {
4266 int char_num;
4267 int chars_num;
4268 int i;
4269 int start_unit_num;
4270 int unit_num;
4271 int presence_p;
4272 pattern_reserv_t pat_reserv;
4273
4274 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4275 for (char_num = 0; char_num < chars_num; char_num++)
4276 if (((unsigned char *) original_set) [char_num])
4277 for (i = CHAR_BIT - 1; i >= 0; i--)
4278 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4279 {
4280 start_unit_num = char_num * CHAR_BIT + i;
4281 if (start_unit_num >= description->units_num)
4282 break;
4283 if ((final_p
4284 && unit_final_presence_set_table [start_unit_num] == NULL)
4285 || (!final_p
4286 && unit_presence_set_table [start_unit_num] == NULL))
4287 continue;
4288 presence_p = FALSE;
4289 for (pat_reserv = (final_p
4290 ? unit_final_presence_set_table [start_unit_num]
4291 : unit_presence_set_table [start_unit_num]);
4292 pat_reserv != NULL;
4293 pat_reserv = pat_reserv->next_pattern_reserv)
4294 {
4295 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4296 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4297 != pat_reserv->reserv [unit_num])
4298 break;
4299 presence_p = presence_p || unit_num >= els_in_cycle_reserv;
4300 }
4301 if (!presence_p)
4302 return FALSE;
4303 }
4304 return TRUE;
4305 }
4306
4307 /* The function checks that CHECKED_SET satisfies all absence pattern
4308 sets for units in ORIGINAL_SET. The function returns TRUE if it
4309 is ok. */
4310 static int
4311 check_absence_pattern_sets (reserv_sets_t checked_set,
4312 reserv_sets_t original_set,
4313 int final_p)
4314 {
4315 int char_num;
4316 int chars_num;
4317 int i;
4318 int start_unit_num;
4319 int unit_num;
4320 pattern_reserv_t pat_reserv;
4321
4322 chars_num = els_in_cycle_reserv * sizeof (set_el_t);
4323 for (char_num = 0; char_num < chars_num; char_num++)
4324 if (((unsigned char *) original_set) [char_num])
4325 for (i = CHAR_BIT - 1; i >= 0; i--)
4326 if ((((unsigned char *) original_set) [char_num] >> i) & 1)
4327 {
4328 start_unit_num = char_num * CHAR_BIT + i;
4329 if (start_unit_num >= description->units_num)
4330 break;
4331 for (pat_reserv = (final_p
4332 ? unit_final_absence_set_table [start_unit_num]
4333 : unit_absence_set_table [start_unit_num]);
4334 pat_reserv != NULL;
4335 pat_reserv = pat_reserv->next_pattern_reserv)
4336 {
4337 for (unit_num = 0; unit_num < els_in_cycle_reserv; unit_num++)
4338 if ((checked_set [unit_num] & pat_reserv->reserv [unit_num])
4339 != pat_reserv->reserv [unit_num]
4340 && pat_reserv->reserv [unit_num])
4341 break;
4342 if (unit_num >= els_in_cycle_reserv)
4343 return FALSE;
4344 }
4345 }
4346 return TRUE;
4347 }
4348
4349
4350
4351 /* This page contains code for transformation of original reservations
4352 described in .md file. The main goal of transformations is
4353 simplifying reservation and lifting up all `|' on the top of IR
4354 reservation representation. */
4355
4356
4357 /* The following function makes copy of IR representation of
4358 reservation. The function also substitutes all reservations
4359 defined by define_reservation by corresponding value during making
4360 the copy. */
4361 static regexp_t
4362 copy_insn_regexp (regexp_t regexp)
4363 {
4364 regexp_t result;
4365 int i;
4366
4367 switch (regexp->mode)
4368 {
4369 case rm_reserv:
4370 result = copy_insn_regexp (REGEXP_RESERV (regexp)->reserv_decl->regexp);
4371 break;
4372
4373 case rm_unit:
4374 result = XCOPYNODE (struct regexp, regexp);
4375 break;
4376
4377 case rm_repeat:
4378 result = XCOPYNODE (struct regexp, regexp);
4379 REGEXP_REPEAT (result)->regexp
4380 = copy_insn_regexp (REGEXP_REPEAT (regexp)->regexp);
4381 break;
4382
4383 case rm_sequence:
4384 result = XCOPYNODEVAR (struct regexp, regexp,
4385 sizeof (struct regexp) + sizeof (regexp_t)
4386 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4387 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4388 REGEXP_SEQUENCE (result)->regexps [i]
4389 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4390 break;
4391
4392 case rm_allof:
4393 result = XCOPYNODEVAR (struct regexp, regexp,
4394 sizeof (struct regexp) + sizeof (regexp_t)
4395 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4396 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4397 REGEXP_ALLOF (result)->regexps [i]
4398 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4399 break;
4400
4401 case rm_oneof:
4402 result = XCOPYNODEVAR (struct regexp, regexp,
4403 sizeof (struct regexp) + sizeof (regexp_t)
4404 * (REGEXP_ONEOF (regexp)->regexps_num - 1));
4405 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4406 REGEXP_ONEOF (result)->regexps [i]
4407 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4408 break;
4409
4410 case rm_nothing:
4411 result = XCOPYNODE (struct regexp, regexp);
4412 break;
4413
4414 default:
4415 gcc_unreachable ();
4416 }
4417 return result;
4418 }
4419
4420 /* The following variable is set up 1 if a transformation has been
4421 applied. */
4422 static int regexp_transformed_p;
4423
4424 /* The function makes transformation
4425 A*N -> A, A, ... */
4426 static regexp_t
4427 transform_1 (regexp_t regexp)
4428 {
4429 int i;
4430 int repeat_num;
4431 regexp_t operand;
4432 pos_t pos;
4433
4434 if (regexp->mode == rm_repeat)
4435 {
4436 repeat_num = REGEXP_REPEAT (regexp)->repeat_num;
4437 gcc_assert (repeat_num > 1);
4438 operand = REGEXP_REPEAT (regexp)->regexp;
4439 pos = regexp->mode;
4440 regexp = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4441 + sizeof (regexp_t) * (repeat_num - 1));
4442 regexp->mode = rm_sequence;
4443 regexp->pos = pos;
4444 REGEXP_SEQUENCE (regexp)->regexps_num = repeat_num;
4445 for (i = 0; i < repeat_num; i++)
4446 REGEXP_SEQUENCE (regexp)->regexps [i] = copy_insn_regexp (operand);
4447 regexp_transformed_p = 1;
4448 }
4449 return regexp;
4450 }
4451
4452 /* The function makes transformations
4453 ...,(A,B,...),C,... -> ...,A,B,...,C,...
4454 ...+(A+B+...)+C+... -> ...+A+B+...+C+...
4455 ...|(A|B|...)|C|... -> ...|A|B|...|C|... */
4456 static regexp_t
4457 transform_2 (regexp_t regexp)
4458 {
4459 if (regexp->mode == rm_sequence)
4460 {
4461 regexp_t sequence = NULL;
4462 regexp_t result;
4463 int sequence_index = 0;
4464 int i, j;
4465
4466 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4467 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_sequence)
4468 {
4469 sequence_index = i;
4470 sequence = REGEXP_SEQUENCE (regexp)->regexps [i];
4471 break;
4472 }
4473 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4474 {
4475 gcc_assert (REGEXP_SEQUENCE (sequence)->regexps_num > 1
4476 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4477 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4478 + sizeof (regexp_t)
4479 * (REGEXP_SEQUENCE (regexp)->regexps_num
4480 + REGEXP_SEQUENCE (sequence)->regexps_num
4481 - 2));
4482 result->mode = rm_sequence;
4483 result->pos = regexp->pos;
4484 REGEXP_SEQUENCE (result)->regexps_num
4485 = (REGEXP_SEQUENCE (regexp)->regexps_num
4486 + REGEXP_SEQUENCE (sequence)->regexps_num - 1);
4487 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4488 if (i < sequence_index)
4489 REGEXP_SEQUENCE (result)->regexps [i]
4490 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4491 else if (i > sequence_index)
4492 REGEXP_SEQUENCE (result)->regexps
4493 [i + REGEXP_SEQUENCE (sequence)->regexps_num - 1]
4494 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
4495 else
4496 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4497 REGEXP_SEQUENCE (result)->regexps [i + j]
4498 = copy_insn_regexp (REGEXP_SEQUENCE (sequence)->regexps [j]);
4499 regexp_transformed_p = 1;
4500 regexp = result;
4501 }
4502 }
4503 else if (regexp->mode == rm_allof)
4504 {
4505 regexp_t allof = NULL;
4506 regexp_t result;
4507 int allof_index = 0;
4508 int i, j;
4509
4510 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4511 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_allof)
4512 {
4513 allof_index = i;
4514 allof = REGEXP_ALLOF (regexp)->regexps [i];
4515 break;
4516 }
4517 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4518 {
4519 gcc_assert (REGEXP_ALLOF (allof)->regexps_num > 1
4520 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4521 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4522 + sizeof (regexp_t)
4523 * (REGEXP_ALLOF (regexp)->regexps_num
4524 + REGEXP_ALLOF (allof)->regexps_num - 2));
4525 result->mode = rm_allof;
4526 result->pos = regexp->pos;
4527 REGEXP_ALLOF (result)->regexps_num
4528 = (REGEXP_ALLOF (regexp)->regexps_num
4529 + REGEXP_ALLOF (allof)->regexps_num - 1);
4530 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4531 if (i < allof_index)
4532 REGEXP_ALLOF (result)->regexps [i]
4533 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4534 else if (i > allof_index)
4535 REGEXP_ALLOF (result)->regexps
4536 [i + REGEXP_ALLOF (allof)->regexps_num - 1]
4537 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
4538 else
4539 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4540 REGEXP_ALLOF (result)->regexps [i + j]
4541 = copy_insn_regexp (REGEXP_ALLOF (allof)->regexps [j]);
4542 regexp_transformed_p = 1;
4543 regexp = result;
4544 }
4545 }
4546 else if (regexp->mode == rm_oneof)
4547 {
4548 regexp_t oneof = NULL;
4549 regexp_t result;
4550 int oneof_index = 0;
4551 int i, j;
4552
4553 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4554 if (REGEXP_ONEOF (regexp)->regexps [i]->mode == rm_oneof)
4555 {
4556 oneof_index = i;
4557 oneof = REGEXP_ONEOF (regexp)->regexps [i];
4558 break;
4559 }
4560 if (i < REGEXP_ONEOF (regexp)->regexps_num)
4561 {
4562 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4563 && REGEXP_ONEOF (regexp)->regexps_num > 1);
4564 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4565 + sizeof (regexp_t)
4566 * (REGEXP_ONEOF (regexp)->regexps_num
4567 + REGEXP_ONEOF (oneof)->regexps_num - 2));
4568 result->mode = rm_oneof;
4569 result->pos = regexp->pos;
4570 REGEXP_ONEOF (result)->regexps_num
4571 = (REGEXP_ONEOF (regexp)->regexps_num
4572 + REGEXP_ONEOF (oneof)->regexps_num - 1);
4573 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4574 if (i < oneof_index)
4575 REGEXP_ONEOF (result)->regexps [i]
4576 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4577 else if (i > oneof_index)
4578 REGEXP_ONEOF (result)->regexps
4579 [i + REGEXP_ONEOF (oneof)->regexps_num - 1]
4580 = copy_insn_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
4581 else
4582 for (j = 0; j < REGEXP_ONEOF (oneof)->regexps_num; j++)
4583 REGEXP_ONEOF (result)->regexps [i + j]
4584 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [j]);
4585 regexp_transformed_p = 1;
4586 regexp = result;
4587 }
4588 }
4589 return regexp;
4590 }
4591
4592 /* The function makes transformations
4593 ...,A|B|...,C,... -> (...,A,C,...)|(...,B,C,...)|...
4594 ...+(A|B|...)+C+... -> (...+A+C+...)|(...+B+C+...)|...
4595 ...+(A,B,...)+C+... -> (...+A+C+...),B,...
4596 ...+(A,B,...)+(C,D,...) -> (A+C),(B+D),... */
4597 static regexp_t
4598 transform_3 (regexp_t regexp)
4599 {
4600 if (regexp->mode == rm_sequence)
4601 {
4602 regexp_t oneof = NULL;
4603 int oneof_index = 0;
4604 regexp_t result;
4605 regexp_t sequence;
4606 int i, j;
4607
4608 for (i = 0; i <REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4609 if (REGEXP_SEQUENCE (regexp)->regexps [i]->mode == rm_oneof)
4610 {
4611 oneof_index = i;
4612 oneof = REGEXP_SEQUENCE (regexp)->regexps [i];
4613 break;
4614 }
4615 if (i < REGEXP_SEQUENCE (regexp)->regexps_num)
4616 {
4617 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4618 && REGEXP_SEQUENCE (regexp)->regexps_num > 1);
4619 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4620 + sizeof (regexp_t)
4621 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4622 result->mode = rm_oneof;
4623 result->pos = regexp->pos;
4624 REGEXP_ONEOF (result)->regexps_num
4625 = REGEXP_ONEOF (oneof)->regexps_num;
4626 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4627 {
4628 sequence
4629 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4630 + sizeof (regexp_t)
4631 * (REGEXP_SEQUENCE (regexp)->regexps_num - 1));
4632 sequence->mode = rm_sequence;
4633 sequence->pos = regexp->pos;
4634 REGEXP_SEQUENCE (sequence)->regexps_num
4635 = REGEXP_SEQUENCE (regexp)->regexps_num;
4636 REGEXP_ONEOF (result)->regexps [i] = sequence;
4637 for (j = 0; j < REGEXP_SEQUENCE (sequence)->regexps_num; j++)
4638 if (j != oneof_index)
4639 REGEXP_SEQUENCE (sequence)->regexps [j]
4640 = copy_insn_regexp (REGEXP_SEQUENCE (regexp)->regexps [j]);
4641 else
4642 REGEXP_SEQUENCE (sequence)->regexps [j]
4643 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4644 }
4645 regexp_transformed_p = 1;
4646 regexp = result;
4647 }
4648 }
4649 else if (regexp->mode == rm_allof)
4650 {
4651 regexp_t oneof = NULL;
4652 regexp_t seq;
4653 int oneof_index = 0;
4654 int max_seq_length, allof_length;
4655 regexp_t result;
4656 regexp_t allof = NULL;
4657 regexp_t allof_op = NULL;
4658 int i, j;
4659
4660 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4661 if (REGEXP_ALLOF (regexp)->regexps [i]->mode == rm_oneof)
4662 {
4663 oneof_index = i;
4664 oneof = REGEXP_ALLOF (regexp)->regexps [i];
4665 break;
4666 }
4667 if (i < REGEXP_ALLOF (regexp)->regexps_num)
4668 {
4669 gcc_assert (REGEXP_ONEOF (oneof)->regexps_num > 1
4670 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4671 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4672 + sizeof (regexp_t)
4673 * (REGEXP_ONEOF (oneof)->regexps_num - 1));
4674 result->mode = rm_oneof;
4675 result->pos = regexp->pos;
4676 REGEXP_ONEOF (result)->regexps_num
4677 = REGEXP_ONEOF (oneof)->regexps_num;
4678 for (i = 0; i < REGEXP_ONEOF (result)->regexps_num; i++)
4679 {
4680 allof
4681 = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4682 + sizeof (regexp_t)
4683 * (REGEXP_ALLOF (regexp)->regexps_num - 1));
4684 allof->mode = rm_allof;
4685 allof->pos = regexp->pos;
4686 REGEXP_ALLOF (allof)->regexps_num
4687 = REGEXP_ALLOF (regexp)->regexps_num;
4688 REGEXP_ONEOF (result)->regexps [i] = allof;
4689 for (j = 0; j < REGEXP_ALLOF (allof)->regexps_num; j++)
4690 if (j != oneof_index)
4691 REGEXP_ALLOF (allof)->regexps [j]
4692 = copy_insn_regexp (REGEXP_ALLOF (regexp)->regexps [j]);
4693 else
4694 REGEXP_ALLOF (allof)->regexps [j]
4695 = copy_insn_regexp (REGEXP_ONEOF (oneof)->regexps [i]);
4696 }
4697 regexp_transformed_p = 1;
4698 regexp = result;
4699 }
4700 max_seq_length = 0;
4701 if (regexp->mode == rm_allof)
4702 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4703 {
4704 switch (REGEXP_ALLOF (regexp)->regexps [i]->mode)
4705 {
4706 case rm_sequence:
4707 seq = REGEXP_ALLOF (regexp)->regexps [i];
4708 if (max_seq_length < REGEXP_SEQUENCE (seq)->regexps_num)
4709 max_seq_length = REGEXP_SEQUENCE (seq)->regexps_num;
4710 break;
4711
4712 case rm_unit:
4713 case rm_nothing:
4714 break;
4715
4716 default:
4717 max_seq_length = 0;
4718 goto break_for;
4719 }
4720 }
4721 break_for:
4722 if (max_seq_length != 0)
4723 {
4724 gcc_assert (max_seq_length != 1
4725 && REGEXP_ALLOF (regexp)->regexps_num > 1);
4726 result = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4727 + sizeof (regexp_t) * (max_seq_length - 1));
4728 result->mode = rm_sequence;
4729 result->pos = regexp->pos;
4730 REGEXP_SEQUENCE (result)->regexps_num = max_seq_length;
4731 for (i = 0; i < max_seq_length; i++)
4732 {
4733 allof_length = 0;
4734 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4735 switch (REGEXP_ALLOF (regexp)->regexps [j]->mode)
4736 {
4737 case rm_sequence:
4738 if (i < (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4739 ->regexps [j])->regexps_num))
4740 {
4741 allof_op
4742 = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4743 ->regexps [j])
4744 ->regexps [i]);
4745 allof_length++;
4746 }
4747 break;
4748 case rm_unit:
4749 case rm_nothing:
4750 if (i == 0)
4751 {
4752 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4753 allof_length++;
4754 }
4755 break;
4756 default:
4757 break;
4758 }
4759
4760 if (allof_length == 1)
4761 REGEXP_SEQUENCE (result)->regexps [i] = allof_op;
4762 else
4763 {
4764 allof = XCREATENODEVAR (struct regexp, sizeof (struct regexp)
4765 + sizeof (regexp_t)
4766 * (allof_length - 1));
4767 allof->mode = rm_allof;
4768 allof->pos = regexp->pos;
4769 REGEXP_ALLOF (allof)->regexps_num = allof_length;
4770 REGEXP_SEQUENCE (result)->regexps [i] = allof;
4771 allof_length = 0;
4772 for (j = 0; j < REGEXP_ALLOF (regexp)->regexps_num; j++)
4773 if (REGEXP_ALLOF (regexp)->regexps [j]->mode == rm_sequence
4774 && (i <
4775 (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4776 ->regexps [j])->regexps_num)))
4777 {
4778 allof_op = (REGEXP_SEQUENCE (REGEXP_ALLOF (regexp)
4779 ->regexps [j])
4780 ->regexps [i]);
4781 REGEXP_ALLOF (allof)->regexps [allof_length]
4782 = allof_op;
4783 allof_length++;
4784 }
4785 else if (i == 0
4786 && (REGEXP_ALLOF (regexp)->regexps [j]->mode
4787 == rm_unit
4788 || (REGEXP_ALLOF (regexp)->regexps [j]->mode
4789 == rm_nothing)))
4790 {
4791 allof_op = REGEXP_ALLOF (regexp)->regexps [j];
4792 REGEXP_ALLOF (allof)->regexps [allof_length]
4793 = allof_op;
4794 allof_length++;
4795 }
4796 }
4797 }
4798 regexp_transformed_p = 1;
4799 regexp = result;
4800 }
4801 }
4802 return regexp;
4803 }
4804
4805 /* The function traverses IR of reservation and applies transformations
4806 implemented by FUNC. */
4807 static regexp_t
4808 regexp_transform_func (regexp_t regexp, regexp_t (*func) (regexp_t regexp))
4809 {
4810 int i;
4811
4812 switch (regexp->mode)
4813 {
4814 case rm_sequence:
4815 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
4816 REGEXP_SEQUENCE (regexp)->regexps [i]
4817 = regexp_transform_func (REGEXP_SEQUENCE (regexp)->regexps [i],
4818 func);
4819 break;
4820
4821 case rm_allof:
4822 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
4823 REGEXP_ALLOF (regexp)->regexps [i]
4824 = regexp_transform_func (REGEXP_ALLOF (regexp)->regexps [i], func);
4825 break;
4826
4827 case rm_oneof:
4828 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
4829 REGEXP_ONEOF (regexp)->regexps [i]
4830 = regexp_transform_func (REGEXP_ONEOF (regexp)->regexps [i], func);
4831 break;
4832
4833 case rm_repeat:
4834 REGEXP_REPEAT (regexp)->regexp
4835 = regexp_transform_func (REGEXP_REPEAT (regexp)->regexp, func);
4836 break;
4837
4838 case rm_nothing:
4839 case rm_unit:
4840 break;
4841
4842 default:
4843 gcc_unreachable ();
4844 }
4845 return (*func) (regexp);
4846 }
4847
4848 /* The function applies all transformations for IR representation of
4849 reservation REGEXP. */
4850 static regexp_t
4851 transform_regexp (regexp_t regexp)
4852 {
4853 regexp = regexp_transform_func (regexp, transform_1);
4854 do
4855 {
4856 regexp_transformed_p = 0;
4857 regexp = regexp_transform_func (regexp, transform_2);
4858 regexp = regexp_transform_func (regexp, transform_3);
4859 }
4860 while (regexp_transformed_p);
4861 return regexp;
4862 }
4863
4864 /* The function applies all transformations for reservations of all
4865 insn declarations. */
4866 static void
4867 transform_insn_regexps (void)
4868 {
4869 decl_t decl;
4870 int i;
4871
4872 transform_time = create_ticker ();
4873 add_advance_cycle_insn_decl ();
4874 if (progress_flag)
4875 fprintf (stderr, "Reservation transformation...");
4876 for (i = 0; i < description->decls_num; i++)
4877 {
4878 decl = description->decls [i];
4879 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
4880 DECL_INSN_RESERV (decl)->transformed_regexp
4881 = transform_regexp (copy_insn_regexp
4882 (DECL_INSN_RESERV (decl)->regexp));
4883 }
4884 if (progress_flag)
4885 fprintf (stderr, "done\n");
4886 ticker_off (&transform_time);
4887 }
4888
4889
4890
4891 /* The following variable value is TRUE if the first annotated message
4892 about units to automata distribution has been output. */
4893 static int annotation_message_reported_p;
4894
4895 /* The following structure describes usage of a unit in a reservation. */
4896 struct unit_usage
4897 {
4898 unit_decl_t unit_decl;
4899 /* The following forms a list of units used on the same cycle in the
4900 same alternative. */
4901 struct unit_usage *next;
4902 };
4903 typedef struct unit_usage *unit_usage_t;
4904
4905 DEF_VEC_P(unit_usage_t);
4906 DEF_VEC_ALLOC_P(unit_usage_t,heap);
4907
4908 /* Obstack for unit_usage structures. */
4909 static struct obstack unit_usages;
4910
4911 /* VLA for representation of array of pointers to unit usage
4912 structures. There is an element for each combination of
4913 (alternative number, cycle). Unit usages on given cycle in
4914 alternative with given number are referred through element with
4915 index equals to the cycle * number of all alternatives in the regexp
4916 + the alternative number. */
4917 static VEC(unit_usage_t,heap) *cycle_alt_unit_usages;
4918
4919 /* The following function creates the structure unit_usage for UNIT on
4920 CYCLE in REGEXP alternative with ALT_NUM. The structure is made
4921 accessed through cycle_alt_unit_usages. */
4922 static void
4923 store_alt_unit_usage (regexp_t regexp, regexp_t unit, int cycle,
4924 int alt_num)
4925 {
4926 size_t length;
4927 unit_decl_t unit_decl;
4928 unit_usage_t unit_usage_ptr;
4929 int index;
4930
4931 gcc_assert (regexp && regexp->mode == rm_oneof
4932 && alt_num < REGEXP_ONEOF (regexp)->regexps_num);
4933 unit_decl = REGEXP_UNIT (unit)->unit_decl;
4934
4935 length = (cycle + 1) * REGEXP_ONEOF (regexp)->regexps_num;
4936 while (VEC_length (unit_usage_t, cycle_alt_unit_usages) < length)
4937 VEC_safe_push (unit_usage_t,heap, cycle_alt_unit_usages, 0);
4938
4939 obstack_blank (&unit_usages, sizeof (struct unit_usage));
4940 unit_usage_ptr = (struct unit_usage *) obstack_base (&unit_usages);
4941 obstack_finish (&unit_usages);
4942 unit_usage_ptr->unit_decl = unit_decl;
4943 index = cycle * REGEXP_ONEOF (regexp)->regexps_num + alt_num;
4944 unit_usage_ptr->next = VEC_index (unit_usage_t, cycle_alt_unit_usages, index);
4945 VEC_replace (unit_usage_t, cycle_alt_unit_usages, index, unit_usage_ptr);
4946 unit_decl->last_distribution_check_cycle = -1; /* undefined */
4947 }
4948
4949 /* The function processes given REGEXP to find units with the wrong
4950 distribution. */
4951 static void
4952 check_regexp_units_distribution (const char *insn_reserv_name,
4953 regexp_t regexp)
4954 {
4955 int i, j, k, cycle;
4956 regexp_t seq, allof, unit;
4957 struct unit_usage *unit_usage_ptr, *other_unit_usage_ptr;
4958
4959 if (regexp == NULL || regexp->mode != rm_oneof)
4960 return;
4961 /* Store all unit usages in the regexp: */
4962 obstack_init (&unit_usages);
4963 cycle_alt_unit_usages = 0;
4964
4965 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
4966 {
4967 seq = REGEXP_ONEOF (regexp)->regexps [i];
4968 switch (seq->mode)
4969 {
4970 case rm_sequence:
4971 for (j = 0; j < REGEXP_SEQUENCE (seq)->regexps_num; j++)
4972 {
4973 allof = REGEXP_SEQUENCE (seq)->regexps [j];
4974 switch (allof->mode)
4975 {
4976 case rm_allof:
4977 for (k = 0; k < REGEXP_ALLOF (allof)->regexps_num; k++)
4978 {
4979 unit = REGEXP_ALLOF (allof)->regexps [k];
4980 if (unit->mode == rm_unit)
4981 store_alt_unit_usage (regexp, unit, j, i);
4982 else
4983 gcc_assert (unit->mode == rm_nothing);
4984 }
4985 break;
4986
4987 case rm_unit:
4988 store_alt_unit_usage (regexp, allof, j, i);
4989 break;
4990
4991 case rm_nothing:
4992 break;
4993
4994 default:
4995 gcc_unreachable ();
4996 }
4997 }
4998 break;
4999
5000 case rm_allof:
5001 for (k = 0; k < REGEXP_ALLOF (seq)->regexps_num; k++)
5002 {
5003 unit = REGEXP_ALLOF (seq)->regexps [k];
5004 switch (unit->mode)
5005 {
5006 case rm_unit:
5007 store_alt_unit_usage (regexp, unit, 0, i);
5008 break;
5009
5010 case rm_nothing:
5011 break;
5012
5013 default:
5014 gcc_unreachable ();
5015 }
5016 }
5017 break;
5018
5019 case rm_unit:
5020 store_alt_unit_usage (regexp, seq, 0, i);
5021 break;
5022
5023 case rm_nothing:
5024 break;
5025
5026 default:
5027 gcc_unreachable ();
5028 }
5029 }
5030 /* Check distribution: */
5031 for (i = 0; i < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages); i++)
5032 {
5033 cycle = i / REGEXP_ONEOF (regexp)->regexps_num;
5034 for (unit_usage_ptr = VEC_index (unit_usage_t, cycle_alt_unit_usages, i);
5035 unit_usage_ptr != NULL;
5036 unit_usage_ptr = unit_usage_ptr->next)
5037 if (cycle != unit_usage_ptr->unit_decl->last_distribution_check_cycle)
5038 {
5039 unit_usage_ptr->unit_decl->last_distribution_check_cycle = cycle;
5040 for (k = cycle * REGEXP_ONEOF (regexp)->regexps_num;
5041 k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5042 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num;
5043 k++)
5044 {
5045 for (other_unit_usage_ptr
5046 = VEC_index (unit_usage_t, cycle_alt_unit_usages, k);
5047 other_unit_usage_ptr != NULL;
5048 other_unit_usage_ptr = other_unit_usage_ptr->next)
5049 if (unit_usage_ptr->unit_decl->automaton_decl
5050 == other_unit_usage_ptr->unit_decl->automaton_decl)
5051 break;
5052 if (other_unit_usage_ptr == NULL
5053 && (VEC_index (unit_usage_t, cycle_alt_unit_usages, k)
5054 != NULL))
5055 break;
5056 }
5057 if (k < (int) VEC_length (unit_usage_t, cycle_alt_unit_usages)
5058 && k == cycle * REGEXP_ONEOF (regexp)->regexps_num)
5059 {
5060 if (!annotation_message_reported_p)
5061 {
5062 fprintf (stderr, "\n");
5063 error ("The following units do not satisfy units-automata distribution rule");
5064 error (" (A unit of given unit automaton should be on each reserv. altern.)");
5065 annotation_message_reported_p = TRUE;
5066 }
5067 error ("Unit %s, reserv. %s, cycle %d",
5068 unit_usage_ptr->unit_decl->name, insn_reserv_name,
5069 cycle);
5070 }
5071 }
5072 }
5073 VEC_free (unit_usage_t,heap, cycle_alt_unit_usages);
5074 obstack_free (&unit_usages, NULL);
5075 }
5076
5077 /* The function finds units which violates units to automata
5078 distribution rule. If the units exist, report about them. */
5079 static void
5080 check_unit_distributions_to_automata (void)
5081 {
5082 decl_t decl;
5083 int i;
5084
5085 if (progress_flag)
5086 fprintf (stderr, "Check unit distributions to automata...");
5087 annotation_message_reported_p = FALSE;
5088 for (i = 0; i < description->decls_num; i++)
5089 {
5090 decl = description->decls [i];
5091 if (decl->mode == dm_insn_reserv)
5092 check_regexp_units_distribution
5093 (DECL_INSN_RESERV (decl)->name,
5094 DECL_INSN_RESERV (decl)->transformed_regexp);
5095 }
5096 if (progress_flag)
5097 fprintf (stderr, "done\n");
5098 }
5099
5100
5101
5102 /* The page contains code for building alt_states (see comments for
5103 IR) describing all possible insns reservations of an automaton. */
5104
5105 /* Current state being formed for which the current alt_state
5106 refers. */
5107 static state_t state_being_formed;
5108
5109 /* Current alt_state being formed. */
5110 static alt_state_t alt_state_being_formed;
5111
5112 /* This recursive function processes `,' and units in reservation
5113 REGEXP for forming alt_states of AUTOMATON. It is believed that
5114 CURR_CYCLE is start cycle of all reservation REGEXP. */
5115 static int
5116 process_seq_for_forming_states (regexp_t regexp, automaton_t automaton,
5117 int curr_cycle)
5118 {
5119 int i;
5120
5121 if (regexp == NULL)
5122 return curr_cycle;
5123
5124 switch (regexp->mode)
5125 {
5126 case rm_unit:
5127 if (REGEXP_UNIT (regexp)->unit_decl->corresponding_automaton_num
5128 == automaton->automaton_order_num)
5129 set_state_reserv (state_being_formed, curr_cycle,
5130 REGEXP_UNIT (regexp)->unit_decl->unit_num);
5131 return curr_cycle;
5132
5133 case rm_sequence:
5134 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
5135 curr_cycle
5136 = process_seq_for_forming_states
5137 (REGEXP_SEQUENCE (regexp)->regexps [i], automaton, curr_cycle) + 1;
5138 return curr_cycle;
5139
5140 case rm_allof:
5141 {
5142 int finish_cycle = 0;
5143 int cycle;
5144
5145 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
5146 {
5147 cycle = process_seq_for_forming_states (REGEXP_ALLOF (regexp)
5148 ->regexps [i],
5149 automaton, curr_cycle);
5150 if (finish_cycle < cycle)
5151 finish_cycle = cycle;
5152 }
5153 return finish_cycle;
5154 }
5155
5156 case rm_nothing:
5157 return curr_cycle;
5158
5159 default:
5160 gcc_unreachable ();
5161 }
5162 }
5163
5164 /* This recursive function finishes forming ALT_STATE of AUTOMATON and
5165 inserts alt_state into the table. */
5166 static void
5167 finish_forming_alt_state (alt_state_t alt_state,
5168 automaton_t automaton ATTRIBUTE_UNUSED)
5169 {
5170 state_t state_in_table;
5171 state_t corresponding_state;
5172
5173 corresponding_state = alt_state->state;
5174 state_in_table = insert_state (corresponding_state);
5175 if (state_in_table != corresponding_state)
5176 {
5177 free_state (corresponding_state);
5178 alt_state->state = state_in_table;
5179 }
5180 }
5181
5182 /* The following variable value is current automaton insn for whose
5183 reservation the alt states are created. */
5184 static ainsn_t curr_ainsn;
5185
5186 /* This recursive function processes `|' in reservation REGEXP for
5187 forming alt_states of AUTOMATON. List of the alt states should
5188 have the same order as in the description. */
5189 static void
5190 process_alts_for_forming_states (regexp_t regexp, automaton_t automaton,
5191 int inside_oneof_p)
5192 {
5193 int i;
5194
5195 if (regexp->mode != rm_oneof)
5196 {
5197 alt_state_being_formed = get_free_alt_state ();
5198 state_being_formed = get_free_state (1, automaton);
5199 alt_state_being_formed->state = state_being_formed;
5200 /* We inserts in reverse order but we process alternatives also
5201 in reverse order. So we have the same order of alternative
5202 as in the description. */
5203 alt_state_being_formed->next_alt_state = curr_ainsn->alt_states;
5204 curr_ainsn->alt_states = alt_state_being_formed;
5205 (void) process_seq_for_forming_states (regexp, automaton, 0);
5206 finish_forming_alt_state (alt_state_being_formed, automaton);
5207 }
5208 else
5209 {
5210 gcc_assert (!inside_oneof_p);
5211 /* We processes it in reverse order to get list with the same
5212 order as in the description. See also the previous
5213 commentary. */
5214 for (i = REGEXP_ONEOF (regexp)->regexps_num - 1; i >= 0; i--)
5215 process_alts_for_forming_states (REGEXP_ONEOF (regexp)->regexps [i],
5216 automaton, 1);
5217 }
5218 }
5219
5220 /* Create nodes alt_state for all AUTOMATON insns. */
5221 static void
5222 create_alt_states (automaton_t automaton)
5223 {
5224 struct insn_reserv_decl *reserv_decl;
5225
5226 for (curr_ainsn = automaton->ainsn_list;
5227 curr_ainsn != NULL;
5228 curr_ainsn = curr_ainsn->next_ainsn)
5229 {
5230 reserv_decl = curr_ainsn->insn_reserv_decl;
5231 if (reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5232 {
5233 curr_ainsn->alt_states = NULL;
5234 process_alts_for_forming_states (reserv_decl->transformed_regexp,
5235 automaton, 0);
5236 curr_ainsn->sorted_alt_states
5237 = uniq_sort_alt_states (curr_ainsn->alt_states);
5238 }
5239 }
5240 }
5241
5242
5243
5244 /* The page contains major code for building DFA(s) for fast pipeline
5245 hazards recognition. */
5246
5247 /* The function forms list of ainsns of AUTOMATON with the same
5248 reservation. */
5249
5250 static void
5251 form_ainsn_with_same_reservs (automaton_t automaton)
5252 {
5253 ainsn_t curr_ainsn;
5254 size_t i;
5255 VEC(ainsn_t,heap) *last_insns = VEC_alloc (ainsn_t,heap, 150);
5256
5257 for (curr_ainsn = automaton->ainsn_list;
5258 curr_ainsn != NULL;
5259 curr_ainsn = curr_ainsn->next_ainsn)
5260 if (curr_ainsn->insn_reserv_decl
5261 == DECL_INSN_RESERV (advance_cycle_insn_decl))
5262 {
5263 curr_ainsn->next_same_reservs_insn = NULL;
5264 curr_ainsn->first_insn_with_same_reservs = 1;
5265 }
5266 else
5267 {
5268 for (i = 0; i < VEC_length (ainsn_t, last_insns); i++)
5269 if (alt_states_eq
5270 (curr_ainsn->sorted_alt_states,
5271 VEC_index (ainsn_t, last_insns, i)->sorted_alt_states))
5272 break;
5273 curr_ainsn->next_same_reservs_insn = NULL;
5274 if (i < VEC_length (ainsn_t, last_insns))
5275 {
5276 curr_ainsn->first_insn_with_same_reservs = 0;
5277 VEC_index (ainsn_t, last_insns, i)->next_same_reservs_insn
5278 = curr_ainsn;
5279 VEC_replace (ainsn_t, last_insns, i, curr_ainsn);
5280 }
5281 else
5282 {
5283 VEC_safe_push (ainsn_t, heap, last_insns, curr_ainsn);
5284 curr_ainsn->first_insn_with_same_reservs = 1;
5285 }
5286 }
5287 VEC_free (ainsn_t,heap, last_insns);
5288 }
5289
5290 /* Forming unit reservations which can affect creating the automaton
5291 states achieved from a given state. It permits to build smaller
5292 automata in many cases. We would have the same automata after
5293 the minimization without such optimization, but the automaton
5294 right after the building could be huge. So in other words, usage
5295 of reservs_matter means some minimization during building the
5296 automaton. */
5297 static reserv_sets_t
5298 form_reservs_matter (automaton_t automaton)
5299 {
5300 int cycle, unit;
5301 reserv_sets_t reservs_matter = alloc_empty_reserv_sets();
5302
5303 for (cycle = 0; cycle < max_cycles_num; cycle++)
5304 for (unit = 0; unit < description->units_num; unit++)
5305 if (units_array [unit]->automaton_decl
5306 == automaton->corresponding_automaton_decl
5307 && (cycle >= units_array [unit]->min_occ_cycle_num
5308 /* We can not remove queried unit from reservations. */
5309 || units_array [unit]->query_p
5310 /* We can not remove units which are used
5311 `exclusion_set', `presence_set',
5312 `final_presence_set', `absence_set', and
5313 `final_absence_set'. */
5314 || units_array [unit]->in_set_p))
5315 set_unit_reserv (reservs_matter, cycle, unit);
5316 return reservs_matter;
5317 }
5318
5319 /* The following function creates all states of nondeterministic AUTOMATON. */
5320 static void
5321 make_automaton (automaton_t automaton)
5322 {
5323 ainsn_t ainsn;
5324 struct insn_reserv_decl *insn_reserv_decl;
5325 alt_state_t alt_state;
5326 state_t state;
5327 state_t start_state;
5328 state_t state2;
5329 ainsn_t advance_cycle_ainsn;
5330 arc_t added_arc;
5331 VEC(state_t,heap) *state_stack = VEC_alloc(state_t,heap, 150);
5332 int states_n;
5333 reserv_sets_t reservs_matter = form_reservs_matter (automaton);
5334
5335 /* Create the start state (empty state). */
5336 start_state = insert_state (get_free_state (1, automaton));
5337 automaton->start_state = start_state;
5338 start_state->it_was_placed_in_stack_for_NDFA_forming = 1;
5339 VEC_safe_push (state_t,heap, state_stack, start_state);
5340 states_n = 1;
5341 while (VEC_length (state_t, state_stack) != 0)
5342 {
5343 state = VEC_pop (state_t, state_stack);
5344 advance_cycle_ainsn = NULL;
5345 for (ainsn = automaton->ainsn_list;
5346 ainsn != NULL;
5347 ainsn = ainsn->next_ainsn)
5348 if (ainsn->first_insn_with_same_reservs)
5349 {
5350 insn_reserv_decl = ainsn->insn_reserv_decl;
5351 if (insn_reserv_decl != DECL_INSN_RESERV (advance_cycle_insn_decl))
5352 {
5353 /* We process alt_states in the same order as they are
5354 present in the description. */
5355 added_arc = NULL;
5356 for (alt_state = ainsn->alt_states;
5357 alt_state != NULL;
5358 alt_state = alt_state->next_alt_state)
5359 {
5360 state2 = alt_state->state;
5361 if (!intersected_state_reservs_p (state, state2))
5362 {
5363 state2 = states_union (state, state2, reservs_matter);
5364 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5365 {
5366 state2->it_was_placed_in_stack_for_NDFA_forming
5367 = 1;
5368 VEC_safe_push (state_t,heap, state_stack, state2);
5369 states_n++;
5370 if (progress_flag && states_n % 100 == 0)
5371 fprintf (stderr, ".");
5372 }
5373 added_arc = add_arc (state, state2, ainsn);
5374 if (!ndfa_flag)
5375 break;
5376 }
5377 }
5378 if (!ndfa_flag && added_arc != NULL)
5379 {
5380 for (alt_state = ainsn->alt_states;
5381 alt_state != NULL;
5382 alt_state = alt_state->next_alt_state)
5383 state2 = alt_state->state;
5384 }
5385 }
5386 else
5387 advance_cycle_ainsn = ainsn;
5388 }
5389 /* Add transition to advance cycle. */
5390 state2 = state_shift (state, reservs_matter);
5391 if (!state2->it_was_placed_in_stack_for_NDFA_forming)
5392 {
5393 state2->it_was_placed_in_stack_for_NDFA_forming = 1;
5394 VEC_safe_push (state_t,heap, state_stack, state2);
5395 states_n++;
5396 if (progress_flag && states_n % 100 == 0)
5397 fprintf (stderr, ".");
5398 }
5399 gcc_assert (advance_cycle_ainsn);
5400 add_arc (state, state2, advance_cycle_ainsn);
5401 }
5402 VEC_free (state_t,heap, state_stack);
5403 }
5404
5405 /* Form lists of all arcs of STATE marked by the same ainsn. */
5406 static void
5407 form_arcs_marked_by_insn (state_t state)
5408 {
5409 decl_t decl;
5410 arc_t arc;
5411 int i;
5412
5413 for (i = 0; i < description->decls_num; i++)
5414 {
5415 decl = description->decls [i];
5416 if (decl->mode == dm_insn_reserv)
5417 DECL_INSN_RESERV (decl)->arcs_marked_by_insn = NULL;
5418 }
5419 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5420 {
5421 gcc_assert (arc->insn);
5422 arc->next_arc_marked_by_insn
5423 = arc->insn->insn_reserv_decl->arcs_marked_by_insn;
5424 arc->insn->insn_reserv_decl->arcs_marked_by_insn = arc;
5425 }
5426 }
5427
5428 /* The function creates composed state (see comments for IR) from
5429 ORIGINAL_STATE and list of arcs ARCS_MARKED_BY_INSN marked by the
5430 same insn. If the composed state is not in STATE_STACK yet, it is
5431 pushed into STATE_STACK. */
5432
5433 static int
5434 create_composed_state (state_t original_state, arc_t arcs_marked_by_insn,
5435 VEC(state_t,heap) **state_stack)
5436 {
5437 state_t state;
5438 alt_state_t alt_state, curr_alt_state;
5439 alt_state_t new_alt_state;
5440 arc_t curr_arc;
5441 arc_t next_arc;
5442 state_t state_in_table;
5443 state_t temp_state;
5444 alt_state_t canonical_alt_states_list;
5445 int alts_number;
5446 int new_state_p = 0;
5447
5448 if (arcs_marked_by_insn == NULL)
5449 return new_state_p;
5450 if (arcs_marked_by_insn->next_arc_marked_by_insn == NULL)
5451 state = arcs_marked_by_insn->to_state;
5452 else
5453 {
5454 gcc_assert (ndfa_flag);
5455 /* Create composed state. */
5456 state = get_free_state (0, arcs_marked_by_insn->to_state->automaton);
5457 curr_alt_state = NULL;
5458 for (curr_arc = arcs_marked_by_insn;
5459 curr_arc != NULL;
5460 curr_arc = curr_arc->next_arc_marked_by_insn)
5461 if (curr_arc->to_state->component_states == NULL)
5462 {
5463 new_alt_state = get_free_alt_state ();
5464 new_alt_state->next_alt_state = curr_alt_state;
5465 new_alt_state->state = curr_arc->to_state;
5466 curr_alt_state = new_alt_state;
5467 }
5468 else
5469 for (alt_state = curr_arc->to_state->component_states;
5470 alt_state != NULL;
5471 alt_state = alt_state->next_sorted_alt_state)
5472 {
5473 new_alt_state = get_free_alt_state ();
5474 new_alt_state->next_alt_state = curr_alt_state;
5475 new_alt_state->state = alt_state->state;
5476 gcc_assert (!alt_state->state->component_states);
5477 curr_alt_state = new_alt_state;
5478 }
5479 /* There are not identical sets in the alt state list. */
5480 canonical_alt_states_list = uniq_sort_alt_states (curr_alt_state);
5481 if (canonical_alt_states_list->next_sorted_alt_state == NULL)
5482 {
5483 temp_state = state;
5484 state = canonical_alt_states_list->state;
5485 free_state (temp_state);
5486 }
5487 else
5488 {
5489 state->component_states = canonical_alt_states_list;
5490 state_in_table = insert_state (state);
5491 if (state_in_table != state)
5492 {
5493 gcc_assert
5494 (state_in_table->it_was_placed_in_stack_for_DFA_forming);
5495 free_state (state);
5496 state = state_in_table;
5497 }
5498 else
5499 {
5500 gcc_assert (!state->it_was_placed_in_stack_for_DFA_forming);
5501 new_state_p = 1;
5502 for (curr_alt_state = state->component_states;
5503 curr_alt_state != NULL;
5504 curr_alt_state = curr_alt_state->next_sorted_alt_state)
5505 for (curr_arc = first_out_arc (curr_alt_state->state);
5506 curr_arc != NULL;
5507 curr_arc = next_out_arc (curr_arc))
5508 add_arc (state, curr_arc->to_state, curr_arc->insn);
5509 }
5510 arcs_marked_by_insn->to_state = state;
5511 for (alts_number = 0,
5512 curr_arc = arcs_marked_by_insn->next_arc_marked_by_insn;
5513 curr_arc != NULL;
5514 curr_arc = next_arc)
5515 {
5516 next_arc = curr_arc->next_arc_marked_by_insn;
5517 remove_arc (original_state, curr_arc);
5518 alts_number++;
5519 }
5520 }
5521 }
5522 if (!state->it_was_placed_in_stack_for_DFA_forming)
5523 {
5524 state->it_was_placed_in_stack_for_DFA_forming = 1;
5525 VEC_safe_push (state_t,heap, *state_stack, state);
5526 }
5527 return new_state_p;
5528 }
5529
5530 /* The function transforms nondeterministic AUTOMATON into
5531 deterministic. */
5532
5533 static void
5534 NDFA_to_DFA (automaton_t automaton)
5535 {
5536 state_t start_state;
5537 state_t state;
5538 decl_t decl;
5539 VEC(state_t,heap) *state_stack;
5540 int i;
5541 int states_n;
5542
5543 state_stack = VEC_alloc (state_t,heap, 0);
5544
5545 /* Create the start state (empty state). */
5546 start_state = automaton->start_state;
5547 start_state->it_was_placed_in_stack_for_DFA_forming = 1;
5548 VEC_safe_push (state_t,heap, state_stack, start_state);
5549 states_n = 1;
5550 while (VEC_length (state_t, state_stack) != 0)
5551 {
5552 state = VEC_pop (state_t, state_stack);
5553 form_arcs_marked_by_insn (state);
5554 for (i = 0; i < description->decls_num; i++)
5555 {
5556 decl = description->decls [i];
5557 if (decl->mode == dm_insn_reserv
5558 && create_composed_state
5559 (state, DECL_INSN_RESERV (decl)->arcs_marked_by_insn,
5560 &state_stack))
5561 {
5562 states_n++;
5563 if (progress_flag && states_n % 100 == 0)
5564 fprintf (stderr, ".");
5565 }
5566 }
5567 }
5568 VEC_free (state_t,heap, state_stack);
5569 }
5570
5571 /* The following variable value is current number (1, 2, ...) of passing
5572 graph of states. */
5573 static int curr_state_graph_pass_num;
5574
5575 /* This recursive function passes all states achieved from START_STATE
5576 and applies APPLIED_FUNC to them. */
5577 static void
5578 pass_state_graph (state_t start_state, void (*applied_func) (state_t state))
5579 {
5580 arc_t arc;
5581
5582 if (start_state->pass_num == curr_state_graph_pass_num)
5583 return;
5584 start_state->pass_num = curr_state_graph_pass_num;
5585 (*applied_func) (start_state);
5586 for (arc = first_out_arc (start_state);
5587 arc != NULL;
5588 arc = next_out_arc (arc))
5589 pass_state_graph (arc->to_state, applied_func);
5590 }
5591
5592 /* This recursive function passes all states of AUTOMATON and applies
5593 APPLIED_FUNC to them. */
5594 static void
5595 pass_states (automaton_t automaton, void (*applied_func) (state_t state))
5596 {
5597 curr_state_graph_pass_num++;
5598 pass_state_graph (automaton->start_state, applied_func);
5599 }
5600
5601 /* The function initializes code for passing of all states. */
5602 static void
5603 initiate_pass_states (void)
5604 {
5605 curr_state_graph_pass_num = 0;
5606 }
5607
5608 /* The following vla is used for storing pointers to all achieved
5609 states. */
5610 static VEC(state_t,heap) *all_achieved_states;
5611
5612 /* This function is called by function pass_states to add an achieved
5613 STATE. */
5614 static void
5615 add_achieved_state (state_t state)
5616 {
5617 VEC_safe_push (state_t,heap, all_achieved_states, state);
5618 }
5619
5620 /* The function sets up equivalence numbers of insns which mark all
5621 out arcs of STATE by equiv_class_num_1 (if ODD_ITERATION_FLAG has
5622 nonzero value) or by equiv_class_num_2 of the destination state.
5623 The function returns number of out arcs of STATE. */
5624 static void
5625 set_out_arc_insns_equiv_num (state_t state, int odd_iteration_flag)
5626 {
5627 arc_t arc;
5628
5629 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5630 {
5631 gcc_assert (!arc->insn->insn_reserv_decl->equiv_class_num);
5632 arc->insn->insn_reserv_decl->equiv_class_num
5633 = (odd_iteration_flag
5634 ? arc->to_state->equiv_class_num_1
5635 : arc->to_state->equiv_class_num_2);
5636 gcc_assert (arc->insn->insn_reserv_decl->equiv_class_num);
5637 }
5638 }
5639
5640 /* The function clears equivalence numbers and alt_states in all insns
5641 which mark all out arcs of STATE. */
5642 static void
5643 clear_arc_insns_equiv_num (state_t state)
5644 {
5645 arc_t arc;
5646
5647 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5648 arc->insn->insn_reserv_decl->equiv_class_num = 0;
5649 }
5650
5651
5652 /* The following function returns TRUE if STATE reserves the unit with
5653 UNIT_NUM on the first cycle. */
5654 static int
5655 first_cycle_unit_presence (state_t state, int unit_num)
5656 {
5657 alt_state_t alt_state;
5658
5659 if (state->component_states == NULL)
5660 return test_unit_reserv (state->reservs, 0, unit_num);
5661 else
5662 {
5663 for (alt_state = state->component_states;
5664 alt_state != NULL;
5665 alt_state = alt_state->next_sorted_alt_state)
5666 if (test_unit_reserv (alt_state->state->reservs, 0, unit_num))
5667 return true;
5668 }
5669 return false;
5670 }
5671
5672 /* This fills in the presence_signature[] member of STATE. */
5673 static void
5674 cache_presence (state_t state)
5675 {
5676 int i, num = 0;
5677 unsigned int sz;
5678 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5679 / (sizeof (int) * CHAR_BIT);
5680
5681 state->presence_signature = XCREATENODEVEC (unsigned int, sz);
5682 for (i = 0; i < description->units_num; i++)
5683 if (units_array [i]->query_p)
5684 {
5685 int presence1_p = first_cycle_unit_presence (state, i);
5686 state->presence_signature[num / (sizeof (int) * CHAR_BIT)]
5687 |= (!!presence1_p) << (num % (sizeof (int) * CHAR_BIT));
5688 num++;
5689 }
5690 }
5691
5692 /* The function returns nonzero value if STATE is not equivalent to
5693 ANOTHER_STATE from the same current partition on equivalence
5694 classes. Another state has ANOTHER_STATE_OUT_ARCS_NUM number of
5695 output arcs. Iteration of making equivalence partition is defined
5696 by ODD_ITERATION_FLAG. */
5697 static int
5698 state_is_differed (state_t state, state_t another_state,
5699 int odd_iteration_flag)
5700 {
5701 arc_t arc;
5702 unsigned int sz, si;
5703
5704 gcc_assert (state->num_out_arcs == another_state->num_out_arcs);
5705
5706 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5707 / (sizeof (int) * CHAR_BIT);
5708
5709 for (si = 0; si < sz; si++)
5710 gcc_assert (state->presence_signature[si]
5711 == another_state->presence_signature[si]);
5712
5713 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
5714 {
5715 if ((odd_iteration_flag
5716 ? arc->to_state->equiv_class_num_1
5717 : arc->to_state->equiv_class_num_2)
5718 != arc->insn->insn_reserv_decl->equiv_class_num)
5719 return 1;
5720 }
5721
5722 return 0;
5723 }
5724
5725 /* Compares two states pointed to by STATE_PTR_1 and STATE_PTR_2
5726 and return -1, 0 or 1. This function can be used as predicate for
5727 qsort(). It requires the member presence_signature[] of both
5728 states be filled. */
5729 static int
5730 compare_states_for_equiv (const void *state_ptr_1,
5731 const void *state_ptr_2)
5732 {
5733 const_state_t const s1 = *(const_state_t const*)state_ptr_1;
5734 const_state_t const s2 = *(const_state_t const*)state_ptr_2;
5735 unsigned int sz, si;
5736 if (s1->num_out_arcs < s2->num_out_arcs)
5737 return -1;
5738 else if (s1->num_out_arcs > s2->num_out_arcs)
5739 return 1;
5740
5741 sz = (description->query_units_num + sizeof (int) * CHAR_BIT - 1)
5742 / (sizeof (int) * CHAR_BIT);
5743
5744 for (si = 0; si < sz; si++)
5745 if (s1->presence_signature[si] < s2->presence_signature[si])
5746 return -1;
5747 else if (s1->presence_signature[si] > s2->presence_signature[si])
5748 return 1;
5749 return 0;
5750 }
5751
5752 /* The function makes initial partition of STATES on equivalent
5753 classes and saves it into *CLASSES. This function requires the input
5754 to be sorted via compare_states_for_equiv(). */
5755 static int
5756 init_equiv_class (VEC(state_t,heap) *states, VEC (state_t,heap) **classes)
5757 {
5758 size_t i;
5759 state_t prev = 0;
5760 int class_num = 1;
5761
5762 *classes = VEC_alloc (state_t,heap, 150);
5763 for (i = 0; i < VEC_length (state_t, states); i++)
5764 {
5765 state_t state = VEC_index (state_t, states, i);
5766 if (prev)
5767 {
5768 if (compare_states_for_equiv (&prev, &state) != 0)
5769 {
5770 VEC_safe_push (state_t,heap, *classes, prev);
5771 class_num++;
5772 prev = NULL;
5773 }
5774 }
5775 state->equiv_class_num_1 = class_num;
5776 state->next_equiv_class_state = prev;
5777 prev = state;
5778 }
5779 if (prev)
5780 VEC_safe_push (state_t,heap, *classes, prev);
5781 return class_num;
5782 }
5783
5784 /* The function copies pointers to equivalent states from vla FROM
5785 into vla TO. */
5786 static void
5787 copy_equiv_class (VEC(state_t,heap) **to, VEC(state_t,heap) *from)
5788 {
5789 VEC_free (state_t,heap, *to);
5790 *to = VEC_copy (state_t,heap, from);
5791 }
5792
5793 /* The function processes equivalence class given by its first state,
5794 FIRST_STATE, on odd iteration if ODD_ITERATION_FLAG. If there
5795 are not equivalent states, the function partitions the class
5796 removing nonequivalent states and placing them in
5797 *NEXT_ITERATION_CLASSES, increments *NEW_EQUIV_CLASS_NUM_PTR ans
5798 assigns it to the state equivalence number. If the class has been
5799 partitioned, the function returns nonzero value. */
5800 static int
5801 partition_equiv_class (state_t first_state, int odd_iteration_flag,
5802 VEC(state_t,heap) **next_iteration_classes,
5803 int *new_equiv_class_num_ptr)
5804 {
5805 state_t new_equiv_class;
5806 int partition_p;
5807 state_t curr_state;
5808 state_t prev_state;
5809 state_t next_state;
5810
5811 partition_p = 0;
5812
5813 while (first_state != NULL)
5814 {
5815 new_equiv_class = NULL;
5816 if (first_state->next_equiv_class_state != NULL)
5817 {
5818 /* There are more one states in the class equivalence. */
5819 set_out_arc_insns_equiv_num (first_state, odd_iteration_flag);
5820 for (prev_state = first_state,
5821 curr_state = first_state->next_equiv_class_state;
5822 curr_state != NULL;
5823 curr_state = next_state)
5824 {
5825 next_state = curr_state->next_equiv_class_state;
5826 if (state_is_differed (curr_state, first_state,
5827 odd_iteration_flag))
5828 {
5829 /* Remove curr state from the class equivalence. */
5830 prev_state->next_equiv_class_state = next_state;
5831 /* Add curr state to the new class equivalence. */
5832 curr_state->next_equiv_class_state = new_equiv_class;
5833 if (new_equiv_class == NULL)
5834 (*new_equiv_class_num_ptr)++;
5835 if (odd_iteration_flag)
5836 curr_state->equiv_class_num_2 = *new_equiv_class_num_ptr;
5837 else
5838 curr_state->equiv_class_num_1 = *new_equiv_class_num_ptr;
5839 new_equiv_class = curr_state;
5840 partition_p = 1;
5841 }
5842 else
5843 prev_state = curr_state;
5844 }
5845 clear_arc_insns_equiv_num (first_state);
5846 }
5847 if (new_equiv_class != NULL)
5848 VEC_safe_push (state_t,heap, *next_iteration_classes, new_equiv_class);
5849 first_state = new_equiv_class;
5850 }
5851 return partition_p;
5852 }
5853
5854 /* The function finds equivalent states of AUTOMATON. */
5855 static void
5856 evaluate_equiv_classes (automaton_t automaton,
5857 VEC(state_t,heap) **equiv_classes)
5858 {
5859 int new_equiv_class_num;
5860 int odd_iteration_flag;
5861 int finish_flag;
5862 VEC (state_t,heap) *next_iteration_classes;
5863 size_t i;
5864
5865 all_achieved_states = VEC_alloc (state_t,heap, 1500);
5866 pass_states (automaton, add_achieved_state);
5867 pass_states (automaton, cache_presence);
5868 qsort (VEC_address (state_t, all_achieved_states),
5869 VEC_length (state_t, all_achieved_states),
5870 sizeof (state_t), compare_states_for_equiv);
5871
5872 odd_iteration_flag = 0;
5873 new_equiv_class_num = init_equiv_class (all_achieved_states,
5874 &next_iteration_classes);
5875
5876 do
5877 {
5878 odd_iteration_flag = !odd_iteration_flag;
5879 finish_flag = 1;
5880 copy_equiv_class (equiv_classes, next_iteration_classes);
5881
5882 /* Transfer equiv numbers for the next iteration. */
5883 for (i = 0; i < VEC_length (state_t, all_achieved_states); i++)
5884 if (odd_iteration_flag)
5885 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2
5886 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1;
5887 else
5888 VEC_index (state_t, all_achieved_states, i)->equiv_class_num_1
5889 = VEC_index (state_t, all_achieved_states, i)->equiv_class_num_2;
5890
5891 for (i = 0; i < VEC_length (state_t, *equiv_classes); i++)
5892 if (partition_equiv_class (VEC_index (state_t, *equiv_classes, i),
5893 odd_iteration_flag,
5894 &next_iteration_classes,
5895 &new_equiv_class_num))
5896 finish_flag = 0;
5897 }
5898 while (!finish_flag);
5899 VEC_free (state_t,heap, next_iteration_classes);
5900 VEC_free (state_t,heap, all_achieved_states);
5901 }
5902
5903 /* The function merges equivalent states of AUTOMATON. */
5904 static void
5905 merge_states (automaton_t automaton, VEC(state_t,heap) *equiv_classes)
5906 {
5907 state_t curr_state;
5908 state_t new_state;
5909 state_t first_class_state;
5910 alt_state_t alt_states;
5911 alt_state_t alt_state, new_alt_state;
5912 arc_t curr_arc;
5913 arc_t next_arc;
5914 size_t i;
5915
5916 /* Create states corresponding to equivalence classes containing two
5917 or more states. */
5918 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5919 {
5920 curr_state = VEC_index (state_t, equiv_classes, i);
5921 if (curr_state->next_equiv_class_state != NULL)
5922 {
5923 /* There are more one states in the class equivalence. */
5924 /* Create new compound state. */
5925 new_state = get_free_state (0, automaton);
5926 alt_states = NULL;
5927 first_class_state = curr_state;
5928 for (curr_state = first_class_state;
5929 curr_state != NULL;
5930 curr_state = curr_state->next_equiv_class_state)
5931 {
5932 curr_state->equiv_class_state = new_state;
5933 if (curr_state->component_states == NULL)
5934 {
5935 new_alt_state = get_free_alt_state ();
5936 new_alt_state->state = curr_state;
5937 new_alt_state->next_alt_state = alt_states;
5938 alt_states = new_alt_state;
5939 }
5940 else
5941 for (alt_state = curr_state->component_states;
5942 alt_state != NULL;
5943 alt_state = alt_state->next_sorted_alt_state)
5944 {
5945 new_alt_state = get_free_alt_state ();
5946 new_alt_state->state = alt_state->state;
5947 new_alt_state->next_alt_state = alt_states;
5948 alt_states = new_alt_state;
5949 }
5950 }
5951 /* Its is important that alt states were sorted before and
5952 after merging to have the same querying results. */
5953 new_state->component_states = uniq_sort_alt_states (alt_states);
5954 }
5955 else
5956 curr_state->equiv_class_state = curr_state;
5957 }
5958
5959 for (i = 0; i < VEC_length (state_t, equiv_classes); i++)
5960 {
5961 curr_state = VEC_index (state_t, equiv_classes, i);
5962 if (curr_state->next_equiv_class_state != NULL)
5963 {
5964 first_class_state = curr_state;
5965 /* Create new arcs output from the state corresponding to
5966 equiv class. */
5967 for (curr_arc = first_out_arc (first_class_state);
5968 curr_arc != NULL;
5969 curr_arc = next_out_arc (curr_arc))
5970 add_arc (first_class_state->equiv_class_state,
5971 curr_arc->to_state->equiv_class_state,
5972 curr_arc->insn);
5973 /* Delete output arcs from states of given class equivalence. */
5974 for (curr_state = first_class_state;
5975 curr_state != NULL;
5976 curr_state = curr_state->next_equiv_class_state)
5977 {
5978 if (automaton->start_state == curr_state)
5979 automaton->start_state = curr_state->equiv_class_state;
5980 /* Delete the state and its output arcs. */
5981 for (curr_arc = first_out_arc (curr_state);
5982 curr_arc != NULL;
5983 curr_arc = next_arc)
5984 {
5985 next_arc = next_out_arc (curr_arc);
5986 free_arc (curr_arc);
5987 }
5988 }
5989 }
5990 else
5991 {
5992 /* Change `to_state' of arcs output from the state of given
5993 equivalence class. */
5994 for (curr_arc = first_out_arc (curr_state);
5995 curr_arc != NULL;
5996 curr_arc = next_out_arc (curr_arc))
5997 curr_arc->to_state = curr_arc->to_state->equiv_class_state;
5998 }
5999 }
6000 }
6001
6002 /* The function sets up new_cycle_p for states if there is arc to the
6003 state marked by advance_cycle_insn_decl. */
6004 static void
6005 set_new_cycle_flags (state_t state)
6006 {
6007 arc_t arc;
6008
6009 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6010 if (arc->insn->insn_reserv_decl
6011 == DECL_INSN_RESERV (advance_cycle_insn_decl))
6012 arc->to_state->new_cycle_p = 1;
6013 }
6014
6015 /* The top level function for minimization of deterministic
6016 AUTOMATON. */
6017 static void
6018 minimize_DFA (automaton_t automaton)
6019 {
6020 VEC(state_t,heap) *equiv_classes = 0;
6021
6022 evaluate_equiv_classes (automaton, &equiv_classes);
6023 merge_states (automaton, equiv_classes);
6024 pass_states (automaton, set_new_cycle_flags);
6025
6026 VEC_free (state_t,heap, equiv_classes);
6027 }
6028
6029 /* Values of two variables are counted number of states and arcs in an
6030 automaton. */
6031 static int curr_counted_states_num;
6032 static int curr_counted_arcs_num;
6033
6034 /* The function is called by function `pass_states' to count states
6035 and arcs of an automaton. */
6036 static void
6037 incr_states_and_arcs_nums (state_t state)
6038 {
6039 arc_t arc;
6040
6041 curr_counted_states_num++;
6042 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6043 curr_counted_arcs_num++;
6044 }
6045
6046 /* The function counts states and arcs of AUTOMATON. */
6047 static void
6048 count_states_and_arcs (automaton_t automaton, int *states_num,
6049 int *arcs_num)
6050 {
6051 curr_counted_states_num = 0;
6052 curr_counted_arcs_num = 0;
6053 pass_states (automaton, incr_states_and_arcs_nums);
6054 *states_num = curr_counted_states_num;
6055 *arcs_num = curr_counted_arcs_num;
6056 }
6057
6058 /* The function builds one DFA AUTOMATON for fast pipeline hazards
6059 recognition after checking and simplifying IR of the
6060 description. */
6061 static void
6062 build_automaton (automaton_t automaton)
6063 {
6064 int states_num;
6065 int arcs_num;
6066
6067 ticker_on (&NDFA_time);
6068 if (progress_flag)
6069 {
6070 if (automaton->corresponding_automaton_decl == NULL)
6071 fprintf (stderr, "Create anonymous automaton");
6072 else
6073 fprintf (stderr, "Create automaton `%s'",
6074 automaton->corresponding_automaton_decl->name);
6075 fprintf (stderr, " (1 dot is 100 new states):");
6076 }
6077 make_automaton (automaton);
6078 if (progress_flag)
6079 fprintf (stderr, " done\n");
6080 ticker_off (&NDFA_time);
6081 count_states_and_arcs (automaton, &states_num, &arcs_num);
6082 automaton->NDFA_states_num = states_num;
6083 automaton->NDFA_arcs_num = arcs_num;
6084 ticker_on (&NDFA_to_DFA_time);
6085 if (progress_flag)
6086 {
6087 if (automaton->corresponding_automaton_decl == NULL)
6088 fprintf (stderr, "Make anonymous DFA");
6089 else
6090 fprintf (stderr, "Make DFA `%s'",
6091 automaton->corresponding_automaton_decl->name);
6092 fprintf (stderr, " (1 dot is 100 new states):");
6093 }
6094 NDFA_to_DFA (automaton);
6095 if (progress_flag)
6096 fprintf (stderr, " done\n");
6097 ticker_off (&NDFA_to_DFA_time);
6098 count_states_and_arcs (automaton, &states_num, &arcs_num);
6099 automaton->DFA_states_num = states_num;
6100 automaton->DFA_arcs_num = arcs_num;
6101 if (!no_minimization_flag)
6102 {
6103 ticker_on (&minimize_time);
6104 if (progress_flag)
6105 {
6106 if (automaton->corresponding_automaton_decl == NULL)
6107 fprintf (stderr, "Minimize anonymous DFA...");
6108 else
6109 fprintf (stderr, "Minimize DFA `%s'...",
6110 automaton->corresponding_automaton_decl->name);
6111 }
6112 minimize_DFA (automaton);
6113 if (progress_flag)
6114 fprintf (stderr, "done\n");
6115 ticker_off (&minimize_time);
6116 count_states_and_arcs (automaton, &states_num, &arcs_num);
6117 automaton->minimal_DFA_states_num = states_num;
6118 automaton->minimal_DFA_arcs_num = arcs_num;
6119 }
6120 }
6121
6122
6123
6124 /* The page contains code for enumeration of all states of an automaton. */
6125
6126 /* Variable used for enumeration of all states of an automaton. Its
6127 value is current number of automaton states. */
6128 static int curr_state_order_num;
6129
6130 /* The function is called by function `pass_states' for enumerating
6131 states. */
6132 static void
6133 set_order_state_num (state_t state)
6134 {
6135 state->order_state_num = curr_state_order_num;
6136 curr_state_order_num++;
6137 }
6138
6139 /* The function enumerates all states of AUTOMATON. */
6140 static void
6141 enumerate_states (automaton_t automaton)
6142 {
6143 curr_state_order_num = 0;
6144 pass_states (automaton, set_order_state_num);
6145 automaton->achieved_states_num = curr_state_order_num;
6146 }
6147
6148
6149
6150 /* The page contains code for finding equivalent automaton insns
6151 (ainsns). */
6152
6153 /* The function inserts AINSN into cyclic list
6154 CYCLIC_EQUIV_CLASS_INSN_LIST of ainsns. */
6155 static ainsn_t
6156 insert_ainsn_into_equiv_class (ainsn_t ainsn,
6157 ainsn_t cyclic_equiv_class_insn_list)
6158 {
6159 if (cyclic_equiv_class_insn_list == NULL)
6160 ainsn->next_equiv_class_insn = ainsn;
6161 else
6162 {
6163 ainsn->next_equiv_class_insn
6164 = cyclic_equiv_class_insn_list->next_equiv_class_insn;
6165 cyclic_equiv_class_insn_list->next_equiv_class_insn = ainsn;
6166 }
6167 return ainsn;
6168 }
6169
6170 /* The function deletes equiv_class_insn into cyclic list of
6171 equivalent ainsns. */
6172 static void
6173 delete_ainsn_from_equiv_class (ainsn_t equiv_class_insn)
6174 {
6175 ainsn_t curr_equiv_class_insn;
6176 ainsn_t prev_equiv_class_insn;
6177
6178 prev_equiv_class_insn = equiv_class_insn;
6179 for (curr_equiv_class_insn = equiv_class_insn->next_equiv_class_insn;
6180 curr_equiv_class_insn != equiv_class_insn;
6181 curr_equiv_class_insn = curr_equiv_class_insn->next_equiv_class_insn)
6182 prev_equiv_class_insn = curr_equiv_class_insn;
6183 if (prev_equiv_class_insn != equiv_class_insn)
6184 prev_equiv_class_insn->next_equiv_class_insn
6185 = equiv_class_insn->next_equiv_class_insn;
6186 }
6187
6188 /* The function processes AINSN of a state in order to find equivalent
6189 ainsns. INSN_ARCS_ARRAY is table: code of insn -> out arc of the
6190 state. */
6191 static void
6192 process_insn_equiv_class (ainsn_t ainsn, arc_t *insn_arcs_array)
6193 {
6194 ainsn_t next_insn;
6195 ainsn_t curr_insn;
6196 ainsn_t cyclic_insn_list;
6197 arc_t arc;
6198
6199 gcc_assert (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]);
6200 curr_insn = ainsn;
6201 /* New class of ainsns which are not equivalent to given ainsn. */
6202 cyclic_insn_list = NULL;
6203 do
6204 {
6205 next_insn = curr_insn->next_equiv_class_insn;
6206 arc = insn_arcs_array [curr_insn->insn_reserv_decl->insn_num];
6207 if (arc == NULL
6208 || (insn_arcs_array [ainsn->insn_reserv_decl->insn_num]->to_state
6209 != arc->to_state))
6210 {
6211 delete_ainsn_from_equiv_class (curr_insn);
6212 cyclic_insn_list = insert_ainsn_into_equiv_class (curr_insn,
6213 cyclic_insn_list);
6214 }
6215 curr_insn = next_insn;
6216 }
6217 while (curr_insn != ainsn);
6218 }
6219
6220 /* The function processes STATE in order to find equivalent ainsns. */
6221 static void
6222 process_state_for_insn_equiv_partition (state_t state)
6223 {
6224 arc_t arc;
6225 arc_t *insn_arcs_array = XCNEWVEC (arc_t, description->insns_num);
6226
6227 /* Process insns of the arcs. */
6228 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6229 insn_arcs_array [arc->insn->insn_reserv_decl->insn_num] = arc;
6230 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
6231 process_insn_equiv_class (arc->insn, insn_arcs_array);
6232
6233 free (insn_arcs_array);
6234 }
6235
6236 /* The function searches for equivalent ainsns of AUTOMATON. */
6237 static void
6238 set_insn_equiv_classes (automaton_t automaton)
6239 {
6240 ainsn_t ainsn;
6241 ainsn_t first_insn;
6242 ainsn_t curr_insn;
6243 ainsn_t cyclic_insn_list;
6244 ainsn_t insn_with_same_reservs;
6245 int equiv_classes_num;
6246
6247 /* All insns are included in one equivalence class. */
6248 cyclic_insn_list = NULL;
6249 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6250 if (ainsn->first_insn_with_same_reservs)
6251 cyclic_insn_list = insert_ainsn_into_equiv_class (ainsn,
6252 cyclic_insn_list);
6253 /* Process insns in order to make equivalence partition. */
6254 pass_states (automaton, process_state_for_insn_equiv_partition);
6255 /* Enumerate equiv classes. */
6256 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6257 /* Set undefined value. */
6258 ainsn->insn_equiv_class_num = -1;
6259 equiv_classes_num = 0;
6260 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6261 if (ainsn->insn_equiv_class_num < 0)
6262 {
6263 first_insn = ainsn;
6264 gcc_assert (first_insn->first_insn_with_same_reservs);
6265 first_insn->first_ainsn_with_given_equivalence_num = 1;
6266 curr_insn = first_insn;
6267 do
6268 {
6269 for (insn_with_same_reservs = curr_insn;
6270 insn_with_same_reservs != NULL;
6271 insn_with_same_reservs
6272 = insn_with_same_reservs->next_same_reservs_insn)
6273 insn_with_same_reservs->insn_equiv_class_num = equiv_classes_num;
6274 curr_insn = curr_insn->next_equiv_class_insn;
6275 }
6276 while (curr_insn != first_insn);
6277 equiv_classes_num++;
6278 }
6279 automaton->insn_equiv_classes_num = equiv_classes_num;
6280 }
6281
6282
6283
6284 /* This page contains code for creating DFA(s) and calls functions
6285 building them. */
6286
6287
6288 /* The following value is used to prevent floating point overflow for
6289 estimating an automaton bound. The value should be less DBL_MAX on
6290 the host machine. We use here approximate minimum of maximal
6291 double floating point value required by ANSI C standard. It
6292 will work for non ANSI sun compiler too. */
6293
6294 #define MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND 1.0E37
6295
6296 /* The function estimate size of the single DFA used by PHR (pipeline
6297 hazards recognizer). */
6298 static double
6299 estimate_one_automaton_bound (void)
6300 {
6301 decl_t decl;
6302 double one_automaton_estimation_bound;
6303 double root_value;
6304 int i;
6305
6306 one_automaton_estimation_bound = 1.0;
6307 for (i = 0; i < description->decls_num; i++)
6308 {
6309 decl = description->decls [i];
6310 if (decl->mode == dm_unit)
6311 {
6312 root_value = exp (log (DECL_UNIT (decl)->max_occ_cycle_num
6313 - DECL_UNIT (decl)->min_occ_cycle_num + 1.0)
6314 / automata_num);
6315 if (MAX_FLOATING_POINT_VALUE_FOR_AUTOMATON_BOUND / root_value
6316 > one_automaton_estimation_bound)
6317 one_automaton_estimation_bound *= root_value;
6318 }
6319 }
6320 return one_automaton_estimation_bound;
6321 }
6322
6323 /* The function compares unit declarations according to their maximal
6324 cycle in reservations. */
6325 static int
6326 compare_max_occ_cycle_nums (const void *unit_decl_1,
6327 const void *unit_decl_2)
6328 {
6329 if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6330 < (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6331 return 1;
6332 else if ((DECL_UNIT (*(const_decl_t const*) unit_decl_1)->max_occ_cycle_num)
6333 == (DECL_UNIT (*(const_decl_t const*) unit_decl_2)->max_occ_cycle_num))
6334 return 0;
6335 else
6336 return -1;
6337 }
6338
6339 /* The function makes heuristic assigning automata to units. Actually
6340 efficacy of the algorithm has been checked yet??? */
6341
6342 static void
6343 units_to_automata_heuristic_distr (void)
6344 {
6345 double estimation_bound;
6346 int automaton_num;
6347 int rest_units_num;
6348 double bound_value;
6349 unit_decl_t *unit_decls;
6350 int i, j;
6351
6352 if (description->units_num == 0)
6353 return;
6354 estimation_bound = estimate_one_automaton_bound ();
6355 unit_decls = XNEWVEC (unit_decl_t, description->units_num);
6356
6357 for (i = 0, j = 0; i < description->decls_num; i++)
6358 if (description->decls[i]->mode == dm_unit)
6359 unit_decls[j++] = DECL_UNIT (description->decls[i]);
6360 gcc_assert (j == description->units_num);
6361
6362 qsort (unit_decls, description->units_num,
6363 sizeof (unit_decl_t), compare_max_occ_cycle_nums);
6364
6365 automaton_num = 0;
6366 bound_value = unit_decls[0]->max_occ_cycle_num;
6367 unit_decls[0]->corresponding_automaton_num = automaton_num;
6368
6369 for (i = 1; i < description->units_num; i++)
6370 {
6371 rest_units_num = description->units_num - i + 1;
6372 gcc_assert (automata_num - automaton_num - 1 <= rest_units_num);
6373 if (automaton_num < automata_num - 1
6374 && ((automata_num - automaton_num - 1 == rest_units_num)
6375 || (bound_value
6376 > (estimation_bound
6377 / unit_decls[i]->max_occ_cycle_num))))
6378 {
6379 bound_value = unit_decls[i]->max_occ_cycle_num;
6380 automaton_num++;
6381 }
6382 else
6383 bound_value *= unit_decls[i]->max_occ_cycle_num;
6384 unit_decls[i]->corresponding_automaton_num = automaton_num;
6385 }
6386 gcc_assert (automaton_num == automata_num - 1);
6387 free (unit_decls);
6388 }
6389
6390 /* The functions creates automaton insns for each automata. Automaton
6391 insn is simply insn for given automaton which makes reservation
6392 only of units of the automaton. */
6393 static ainsn_t
6394 create_ainsns (void)
6395 {
6396 decl_t decl;
6397 ainsn_t first_ainsn;
6398 ainsn_t curr_ainsn;
6399 ainsn_t prev_ainsn;
6400 int i;
6401
6402 first_ainsn = NULL;
6403 prev_ainsn = NULL;
6404 for (i = 0; i < description->decls_num; i++)
6405 {
6406 decl = description->decls [i];
6407 if (decl->mode == dm_insn_reserv)
6408 {
6409 curr_ainsn = XCREATENODE (struct ainsn);
6410 curr_ainsn->insn_reserv_decl = DECL_INSN_RESERV (decl);
6411 curr_ainsn->important_p = FALSE;
6412 curr_ainsn->next_ainsn = NULL;
6413 if (prev_ainsn == NULL)
6414 first_ainsn = curr_ainsn;
6415 else
6416 prev_ainsn->next_ainsn = curr_ainsn;
6417 prev_ainsn = curr_ainsn;
6418 }
6419 }
6420 return first_ainsn;
6421 }
6422
6423 /* The function assigns automata to units according to constructions
6424 `define_automaton' in the description. */
6425 static void
6426 units_to_automata_distr (void)
6427 {
6428 decl_t decl;
6429 int i;
6430
6431 for (i = 0; i < description->decls_num; i++)
6432 {
6433 decl = description->decls [i];
6434 if (decl->mode == dm_unit)
6435 {
6436 if (DECL_UNIT (decl)->automaton_decl == NULL
6437 || (DECL_UNIT (decl)->automaton_decl->corresponding_automaton
6438 == NULL))
6439 /* Distribute to the first automaton. */
6440 DECL_UNIT (decl)->corresponding_automaton_num = 0;
6441 else
6442 DECL_UNIT (decl)->corresponding_automaton_num
6443 = (DECL_UNIT (decl)->automaton_decl
6444 ->corresponding_automaton->automaton_order_num);
6445 }
6446 }
6447 }
6448
6449 /* The function creates DFA(s) for fast pipeline hazards recognition
6450 after checking and simplifying IR of the description. */
6451 static void
6452 create_automata (void)
6453 {
6454 automaton_t curr_automaton;
6455 automaton_t prev_automaton;
6456 decl_t decl;
6457 int curr_automaton_num;
6458 int i;
6459
6460 if (automata_num != 0)
6461 {
6462 units_to_automata_heuristic_distr ();
6463 for (prev_automaton = NULL, curr_automaton_num = 0;
6464 curr_automaton_num < automata_num;
6465 curr_automaton_num++, prev_automaton = curr_automaton)
6466 {
6467 curr_automaton = XCREATENODE (struct automaton);
6468 curr_automaton->ainsn_list = create_ainsns ();
6469 curr_automaton->corresponding_automaton_decl = NULL;
6470 curr_automaton->next_automaton = NULL;
6471 curr_automaton->automaton_order_num = curr_automaton_num;
6472 if (prev_automaton == NULL)
6473 description->first_automaton = curr_automaton;
6474 else
6475 prev_automaton->next_automaton = curr_automaton;
6476 }
6477 }
6478 else
6479 {
6480 curr_automaton_num = 0;
6481 prev_automaton = NULL;
6482 for (i = 0; i < description->decls_num; i++)
6483 {
6484 decl = description->decls [i];
6485 if (decl->mode == dm_automaton
6486 && DECL_AUTOMATON (decl)->automaton_is_used)
6487 {
6488 curr_automaton = XCREATENODE (struct automaton);
6489 curr_automaton->ainsn_list = create_ainsns ();
6490 curr_automaton->corresponding_automaton_decl
6491 = DECL_AUTOMATON (decl);
6492 curr_automaton->next_automaton = NULL;
6493 DECL_AUTOMATON (decl)->corresponding_automaton = curr_automaton;
6494 curr_automaton->automaton_order_num = curr_automaton_num;
6495 if (prev_automaton == NULL)
6496 description->first_automaton = curr_automaton;
6497 else
6498 prev_automaton->next_automaton = curr_automaton;
6499 curr_automaton_num++;
6500 prev_automaton = curr_automaton;
6501 }
6502 }
6503 if (curr_automaton_num == 0)
6504 {
6505 curr_automaton = XCREATENODE (struct automaton);
6506 curr_automaton->ainsn_list = create_ainsns ();
6507 curr_automaton->corresponding_automaton_decl = NULL;
6508 curr_automaton->next_automaton = NULL;
6509 description->first_automaton = curr_automaton;
6510 }
6511 units_to_automata_distr ();
6512 }
6513 NDFA_time = create_ticker ();
6514 ticker_off (&NDFA_time);
6515 NDFA_to_DFA_time = create_ticker ();
6516 ticker_off (&NDFA_to_DFA_time);
6517 minimize_time = create_ticker ();
6518 ticker_off (&minimize_time);
6519 equiv_time = create_ticker ();
6520 ticker_off (&equiv_time);
6521 for (curr_automaton = description->first_automaton;
6522 curr_automaton != NULL;
6523 curr_automaton = curr_automaton->next_automaton)
6524 {
6525 if (progress_flag)
6526 {
6527 if (curr_automaton->corresponding_automaton_decl == NULL)
6528 fprintf (stderr, "Prepare anonymous automaton creation ... ");
6529 else
6530 fprintf (stderr, "Prepare automaton `%s' creation...",
6531 curr_automaton->corresponding_automaton_decl->name);
6532 }
6533 create_alt_states (curr_automaton);
6534 form_ainsn_with_same_reservs (curr_automaton);
6535 if (progress_flag)
6536 fprintf (stderr, "done\n");
6537 build_automaton (curr_automaton);
6538 enumerate_states (curr_automaton);
6539 ticker_on (&equiv_time);
6540 set_insn_equiv_classes (curr_automaton);
6541 ticker_off (&equiv_time);
6542 }
6543 }
6544
6545
6546
6547 /* This page contains code for forming string representation of
6548 regexp. The representation is formed on IR obstack. So you should
6549 not work with IR obstack between regexp_representation and
6550 finish_regexp_representation calls. */
6551
6552 /* This recursive function forms string representation of regexp
6553 (without tailing '\0'). */
6554 static void
6555 form_regexp (regexp_t regexp)
6556 {
6557 int i;
6558
6559 switch (regexp->mode)
6560 {
6561 case rm_unit: case rm_reserv:
6562 {
6563 const char *name = (regexp->mode == rm_unit
6564 ? REGEXP_UNIT (regexp)->name
6565 : REGEXP_RESERV (regexp)->name);
6566
6567 obstack_grow (&irp, name, strlen (name));
6568 break;
6569 }
6570
6571 case rm_sequence:
6572 for (i = 0; i < REGEXP_SEQUENCE (regexp)->regexps_num; i++)
6573 {
6574 if (i != 0)
6575 obstack_1grow (&irp, ',');
6576 form_regexp (REGEXP_SEQUENCE (regexp)->regexps [i]);
6577 }
6578 break;
6579
6580 case rm_allof:
6581 obstack_1grow (&irp, '(');
6582 for (i = 0; i < REGEXP_ALLOF (regexp)->regexps_num; i++)
6583 {
6584 if (i != 0)
6585 obstack_1grow (&irp, '+');
6586 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6587 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6588 obstack_1grow (&irp, '(');
6589 form_regexp (REGEXP_ALLOF (regexp)->regexps [i]);
6590 if (REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_sequence
6591 || REGEXP_ALLOF (regexp)->regexps[i]->mode == rm_oneof)
6592 obstack_1grow (&irp, ')');
6593 }
6594 obstack_1grow (&irp, ')');
6595 break;
6596
6597 case rm_oneof:
6598 for (i = 0; i < REGEXP_ONEOF (regexp)->regexps_num; i++)
6599 {
6600 if (i != 0)
6601 obstack_1grow (&irp, '|');
6602 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6603 obstack_1grow (&irp, '(');
6604 form_regexp (REGEXP_ONEOF (regexp)->regexps [i]);
6605 if (REGEXP_ONEOF (regexp)->regexps[i]->mode == rm_sequence)
6606 obstack_1grow (&irp, ')');
6607 }
6608 break;
6609
6610 case rm_repeat:
6611 {
6612 char digits [30];
6613
6614 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6615 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6616 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6617 obstack_1grow (&irp, '(');
6618 form_regexp (REGEXP_REPEAT (regexp)->regexp);
6619 if (REGEXP_REPEAT (regexp)->regexp->mode == rm_sequence
6620 || REGEXP_REPEAT (regexp)->regexp->mode == rm_allof
6621 || REGEXP_REPEAT (regexp)->regexp->mode == rm_oneof)
6622 obstack_1grow (&irp, ')');
6623 sprintf (digits, "*%d", REGEXP_REPEAT (regexp)->repeat_num);
6624 obstack_grow (&irp, digits, strlen (digits));
6625 break;
6626 }
6627
6628 case rm_nothing:
6629 obstack_grow (&irp, NOTHING_NAME, strlen (NOTHING_NAME));
6630 break;
6631
6632 default:
6633 gcc_unreachable ();
6634 }
6635 }
6636
6637 /* The function returns string representation of REGEXP on IR
6638 obstack. */
6639 static const char *
6640 regexp_representation (regexp_t regexp)
6641 {
6642 form_regexp (regexp);
6643 obstack_1grow (&irp, '\0');
6644 return obstack_base (&irp);
6645 }
6646
6647 /* The function frees memory allocated for last formed string
6648 representation of regexp. */
6649 static void
6650 finish_regexp_representation (void)
6651 {
6652 int length = obstack_object_size (&irp);
6653
6654 obstack_blank_fast (&irp, -length);
6655 }
6656
6657
6658
6659 /* This page contains code for output PHR (pipeline hazards recognizer). */
6660
6661 /* The function outputs minimal C type which is sufficient for
6662 representation numbers in range min_range_value and
6663 max_range_value. Because host machine and build machine may be
6664 different, we use here minimal values required by ANSI C standard
6665 instead of UCHAR_MAX, SHRT_MAX, SHRT_MIN, etc. This is a good
6666 approximation. */
6667
6668 static void
6669 output_range_type (FILE *f, long int min_range_value,
6670 long int max_range_value)
6671 {
6672 if (min_range_value >= 0 && max_range_value <= 255)
6673 fprintf (f, "unsigned char");
6674 else if (min_range_value >= -127 && max_range_value <= 127)
6675 fprintf (f, "signed char");
6676 else if (min_range_value >= 0 && max_range_value <= 65535)
6677 fprintf (f, "unsigned short");
6678 else if (min_range_value >= -32767 && max_range_value <= 32767)
6679 fprintf (f, "short");
6680 else
6681 fprintf (f, "int");
6682 }
6683
6684 /* The function outputs all initialization values of VECT. */
6685 static void
6686 output_vect (vla_hwint_t vect)
6687 {
6688 int els_on_line;
6689 size_t vect_length = VEC_length (vect_el_t, vect);
6690 size_t i;
6691
6692 els_on_line = 1;
6693 if (vect_length == 0)
6694 fputs ("0 /* This is dummy el because the vect is empty */", output_file);
6695 else
6696 for (i = 0; i < vect_length; i++)
6697 {
6698 fprintf (output_file, "%5ld", (long) VEC_index (vect_el_t, vect, i));
6699 if (els_on_line == 10)
6700 {
6701 els_on_line = 0;
6702 fputs (",\n", output_file);
6703 }
6704 else if (i < vect_length-1)
6705 fputs (", ", output_file);
6706 els_on_line++;
6707 }
6708 }
6709
6710 /* The following is name of the structure which represents DFA(s) for
6711 PHR. */
6712 #define CHIP_NAME "DFA_chip"
6713
6714 /* The following is name of member which represents state of a DFA for
6715 PHR. */
6716 static void
6717 output_chip_member_name (FILE *f, automaton_t automaton)
6718 {
6719 if (automaton->corresponding_automaton_decl == NULL)
6720 fprintf (f, "automaton_state_%d", automaton->automaton_order_num);
6721 else
6722 fprintf (f, "%s_automaton_state",
6723 automaton->corresponding_automaton_decl->name);
6724 }
6725
6726 /* The following is name of temporary variable which stores state of a
6727 DFA for PHR. */
6728 static void
6729 output_temp_chip_member_name (FILE *f, automaton_t automaton)
6730 {
6731 fprintf (f, "_");
6732 output_chip_member_name (f, automaton);
6733 }
6734
6735 /* This is name of macro value which is code of pseudo_insn
6736 representing advancing cpu cycle. Its value is used as internal
6737 code unknown insn. */
6738 #define ADVANCE_CYCLE_VALUE_NAME "DFA__ADVANCE_CYCLE"
6739
6740 /* Output name of translate vector for given automaton. */
6741 static void
6742 output_translate_vect_name (FILE *f, automaton_t automaton)
6743 {
6744 if (automaton->corresponding_automaton_decl == NULL)
6745 fprintf (f, "translate_%d", automaton->automaton_order_num);
6746 else
6747 fprintf (f, "%s_translate", automaton->corresponding_automaton_decl->name);
6748 }
6749
6750 /* Output name for simple transition table representation. */
6751 static void
6752 output_trans_full_vect_name (FILE *f, automaton_t automaton)
6753 {
6754 if (automaton->corresponding_automaton_decl == NULL)
6755 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6756 else
6757 fprintf (f, "%s_transitions",
6758 automaton->corresponding_automaton_decl->name);
6759 }
6760
6761 /* Output name of comb vector of the transition table for given
6762 automaton. */
6763 static void
6764 output_trans_comb_vect_name (FILE *f, automaton_t automaton)
6765 {
6766 if (automaton->corresponding_automaton_decl == NULL)
6767 fprintf (f, "transitions_%d", automaton->automaton_order_num);
6768 else
6769 fprintf (f, "%s_transitions",
6770 automaton->corresponding_automaton_decl->name);
6771 }
6772
6773 /* Output name of check vector of the transition table for given
6774 automaton. */
6775 static void
6776 output_trans_check_vect_name (FILE *f, automaton_t automaton)
6777 {
6778 if (automaton->corresponding_automaton_decl == NULL)
6779 fprintf (f, "check_%d", automaton->automaton_order_num);
6780 else
6781 fprintf (f, "%s_check", automaton->corresponding_automaton_decl->name);
6782 }
6783
6784 /* Output name of base vector of the transition table for given
6785 automaton. */
6786 static void
6787 output_trans_base_vect_name (FILE *f, automaton_t automaton)
6788 {
6789 if (automaton->corresponding_automaton_decl == NULL)
6790 fprintf (f, "base_%d", automaton->automaton_order_num);
6791 else
6792 fprintf (f, "%s_base", automaton->corresponding_automaton_decl->name);
6793 }
6794
6795 /* Output name of simple min issue delay table representation. */
6796 static void
6797 output_min_issue_delay_vect_name (FILE *f, automaton_t automaton)
6798 {
6799 if (automaton->corresponding_automaton_decl == NULL)
6800 fprintf (f, "min_issue_delay_%d", automaton->automaton_order_num);
6801 else
6802 fprintf (f, "%s_min_issue_delay",
6803 automaton->corresponding_automaton_decl->name);
6804 }
6805
6806 /* Output name of deadlock vector for given automaton. */
6807 static void
6808 output_dead_lock_vect_name (FILE *f, automaton_t automaton)
6809 {
6810 if (automaton->corresponding_automaton_decl == NULL)
6811 fprintf (f, "dead_lock_%d", automaton->automaton_order_num);
6812 else
6813 fprintf (f, "%s_dead_lock", automaton->corresponding_automaton_decl->name);
6814 }
6815
6816 /* Output name of reserved units table for AUTOMATON into file F. */
6817 static void
6818 output_reserved_units_table_name (FILE *f, automaton_t automaton)
6819 {
6820 if (automaton->corresponding_automaton_decl == NULL)
6821 fprintf (f, "reserved_units_%d", automaton->automaton_order_num);
6822 else
6823 fprintf (f, "%s_reserved_units",
6824 automaton->corresponding_automaton_decl->name);
6825 }
6826
6827 /* Name of the PHR interface macro. */
6828 #define CPU_UNITS_QUERY_MACRO_NAME "CPU_UNITS_QUERY"
6829
6830 /* Names of an internal functions: */
6831 #define INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME "internal_min_issue_delay"
6832
6833 /* This is external type of DFA(s) state. */
6834 #define STATE_TYPE_NAME "state_t"
6835
6836 #define INTERNAL_TRANSITION_FUNC_NAME "internal_state_transition"
6837
6838 #define INTERNAL_RESET_FUNC_NAME "internal_reset"
6839
6840 #define INTERNAL_DEAD_LOCK_FUNC_NAME "internal_state_dead_lock_p"
6841
6842 #define INTERNAL_INSN_LATENCY_FUNC_NAME "internal_insn_latency"
6843
6844 /* Name of cache of insn dfa codes. */
6845 #define DFA_INSN_CODES_VARIABLE_NAME "dfa_insn_codes"
6846
6847 /* Name of length of cache of insn dfa codes. */
6848 #define DFA_INSN_CODES_LENGTH_VARIABLE_NAME "dfa_insn_codes_length"
6849
6850 /* Names of the PHR interface functions: */
6851 #define SIZE_FUNC_NAME "state_size"
6852
6853 #define TRANSITION_FUNC_NAME "state_transition"
6854
6855 #define MIN_ISSUE_DELAY_FUNC_NAME "min_issue_delay"
6856
6857 #define MIN_INSN_CONFLICT_DELAY_FUNC_NAME "min_insn_conflict_delay"
6858
6859 #define DEAD_LOCK_FUNC_NAME "state_dead_lock_p"
6860
6861 #define RESET_FUNC_NAME "state_reset"
6862
6863 #define INSN_LATENCY_FUNC_NAME "insn_latency"
6864
6865 #define PRINT_RESERVATION_FUNC_NAME "print_reservation"
6866
6867 #define GET_CPU_UNIT_CODE_FUNC_NAME "get_cpu_unit_code"
6868
6869 #define CPU_UNIT_RESERVATION_P_FUNC_NAME "cpu_unit_reservation_p"
6870
6871 #define INSN_HAS_DFA_RESERVATION_P_FUNC_NAME "insn_has_dfa_reservation_p"
6872
6873 #define DFA_CLEAN_INSN_CACHE_FUNC_NAME "dfa_clean_insn_cache"
6874
6875 #define DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME "dfa_clear_single_insn_cache"
6876
6877 #define DFA_START_FUNC_NAME "dfa_start"
6878
6879 #define DFA_FINISH_FUNC_NAME "dfa_finish"
6880
6881 /* Names of parameters of the PHR interface functions. */
6882 #define STATE_NAME "state"
6883
6884 #define INSN_PARAMETER_NAME "insn"
6885
6886 #define INSN2_PARAMETER_NAME "insn2"
6887
6888 #define CHIP_PARAMETER_NAME "chip"
6889
6890 #define FILE_PARAMETER_NAME "f"
6891
6892 #define CPU_UNIT_NAME_PARAMETER_NAME "cpu_unit_name"
6893
6894 #define CPU_CODE_PARAMETER_NAME "cpu_unit_code"
6895
6896 /* Names of the variables whose values are internal insn code of rtx
6897 insn. */
6898 #define INTERNAL_INSN_CODE_NAME "insn_code"
6899
6900 #define INTERNAL_INSN2_CODE_NAME "insn2_code"
6901
6902 /* Names of temporary variables in some functions. */
6903 #define TEMPORARY_VARIABLE_NAME "temp"
6904
6905 #define I_VARIABLE_NAME "i"
6906
6907 /* Name of result variable in some functions. */
6908 #define RESULT_VARIABLE_NAME "res"
6909
6910 /* Name of function (attribute) to translate insn into internal insn
6911 code. */
6912 #define INTERNAL_DFA_INSN_CODE_FUNC_NAME "internal_dfa_insn_code"
6913
6914 /* Name of function (attribute) to translate insn into internal insn
6915 code with caching. */
6916 #define DFA_INSN_CODE_FUNC_NAME "dfa_insn_code"
6917
6918 /* Output C type which is used for representation of codes of states
6919 of AUTOMATON. */
6920 static void
6921 output_state_member_type (FILE *f, automaton_t automaton)
6922 {
6923 output_range_type (f, 0, automaton->achieved_states_num);
6924 }
6925
6926 /* Output definition of the structure representing current DFA(s)
6927 state(s). */
6928 static void
6929 output_chip_definitions (void)
6930 {
6931 automaton_t automaton;
6932
6933 fprintf (output_file, "struct %s\n{\n", CHIP_NAME);
6934 for (automaton = description->first_automaton;
6935 automaton != NULL;
6936 automaton = automaton->next_automaton)
6937 {
6938 fprintf (output_file, " ");
6939 output_state_member_type (output_file, automaton);
6940 fprintf (output_file, " ");
6941 output_chip_member_name (output_file, automaton);
6942 fprintf (output_file, ";\n");
6943 }
6944 fprintf (output_file, "};\n\n");
6945 #if 0
6946 fprintf (output_file, "static struct %s %s;\n\n", CHIP_NAME, CHIP_NAME);
6947 #endif
6948 }
6949
6950
6951 /* The function outputs translate vector of internal insn code into
6952 insn equivalence class number. The equivalence class number is
6953 used to access to table and vectors representing DFA(s). */
6954 static void
6955 output_translate_vect (automaton_t automaton)
6956 {
6957 ainsn_t ainsn;
6958 int insn_value;
6959 vla_hwint_t translate_vect;
6960
6961 translate_vect = VEC_alloc (vect_el_t,heap, description->insns_num);
6962
6963 for (insn_value = 0; insn_value < description->insns_num; insn_value++)
6964 /* Undefined value */
6965 VEC_quick_push (vect_el_t, translate_vect,
6966 automaton->insn_equiv_classes_num);
6967
6968 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
6969 VEC_replace (vect_el_t, translate_vect,
6970 ainsn->insn_reserv_decl->insn_num,
6971 ainsn->insn_equiv_class_num);
6972
6973 fprintf (output_file,
6974 "/* Vector translating external insn codes to internal ones.*/\n");
6975 fprintf (output_file, "static const ");
6976 output_range_type (output_file, 0, automaton->insn_equiv_classes_num);
6977 fprintf (output_file, " ");
6978 output_translate_vect_name (output_file, automaton);
6979 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
6980 output_vect (translate_vect);
6981 fprintf (output_file, "};\n\n");
6982 VEC_free (vect_el_t,heap, translate_vect);
6983 }
6984
6985 /* The value in a table state x ainsn -> something which represents
6986 undefined value. */
6987 static int undefined_vect_el_value;
6988
6989 /* The following function returns nonzero value if the best
6990 representation of the table is comb vector. */
6991 static int
6992 comb_vect_p (state_ainsn_table_t tab)
6993 {
6994 return (2 * VEC_length (vect_el_t, tab->full_vect)
6995 > 5 * VEC_length (vect_el_t, tab->comb_vect));
6996 }
6997
6998 /* The following function creates new table for AUTOMATON. */
6999 static state_ainsn_table_t
7000 create_state_ainsn_table (automaton_t automaton)
7001 {
7002 state_ainsn_table_t tab;
7003 int full_vect_length;
7004 int i;
7005
7006 tab = XCREATENODE (struct state_ainsn_table);
7007 tab->automaton = automaton;
7008
7009 tab->comb_vect = VEC_alloc (vect_el_t,heap, 10000);
7010 tab->check_vect = VEC_alloc (vect_el_t,heap, 10000);
7011
7012 tab->base_vect = 0;
7013 VEC_safe_grow (vect_el_t,heap, tab->base_vect,
7014 automaton->achieved_states_num);
7015
7016 full_vect_length = (automaton->insn_equiv_classes_num
7017 * automaton->achieved_states_num);
7018 tab->full_vect = VEC_alloc (vect_el_t,heap, full_vect_length);
7019 for (i = 0; i < full_vect_length; i++)
7020 VEC_quick_push (vect_el_t, tab->full_vect, undefined_vect_el_value);
7021
7022 tab->min_base_vect_el_value = 0;
7023 tab->max_base_vect_el_value = 0;
7024 tab->min_comb_vect_el_value = 0;
7025 tab->max_comb_vect_el_value = 0;
7026 return tab;
7027 }
7028
7029 /* The following function outputs the best C representation of the
7030 table TAB of given TABLE_NAME. */
7031 static void
7032 output_state_ainsn_table (state_ainsn_table_t tab, const char *table_name,
7033 void (*output_full_vect_name_func) (FILE *, automaton_t),
7034 void (*output_comb_vect_name_func) (FILE *, automaton_t),
7035 void (*output_check_vect_name_func) (FILE *, automaton_t),
7036 void (*output_base_vect_name_func) (FILE *, automaton_t))
7037 {
7038 if (!comb_vect_p (tab))
7039 {
7040 fprintf (output_file, "/* Vector for %s. */\n", table_name);
7041 fprintf (output_file, "static const ");
7042 output_range_type (output_file, tab->min_comb_vect_el_value,
7043 tab->max_comb_vect_el_value);
7044 fprintf (output_file, " ");
7045 (*output_full_vect_name_func) (output_file, tab->automaton);
7046 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7047 output_vect (tab->full_vect);
7048 fprintf (output_file, "};\n\n");
7049 }
7050 else
7051 {
7052 fprintf (output_file, "/* Comb vector for %s. */\n", table_name);
7053 fprintf (output_file, "static const ");
7054 output_range_type (output_file, tab->min_comb_vect_el_value,
7055 tab->max_comb_vect_el_value);
7056 fprintf (output_file, " ");
7057 (*output_comb_vect_name_func) (output_file, tab->automaton);
7058 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7059 output_vect (tab->comb_vect);
7060 fprintf (output_file, "};\n\n");
7061 fprintf (output_file, "/* Check vector for %s. */\n", table_name);
7062 fprintf (output_file, "static const ");
7063 output_range_type (output_file, 0, tab->automaton->achieved_states_num);
7064 fprintf (output_file, " ");
7065 (*output_check_vect_name_func) (output_file, tab->automaton);
7066 fprintf (output_file, "[] = {\n");
7067 output_vect (tab->check_vect);
7068 fprintf (output_file, "};\n\n");
7069 fprintf (output_file, "/* Base vector for %s. */\n", table_name);
7070 fprintf (output_file, "static const ");
7071 output_range_type (output_file, tab->min_base_vect_el_value,
7072 tab->max_base_vect_el_value);
7073 fprintf (output_file, " ");
7074 (*output_base_vect_name_func) (output_file, tab->automaton);
7075 fprintf (output_file, "[] = {\n");
7076 output_vect (tab->base_vect);
7077 fprintf (output_file, "};\n\n");
7078 }
7079 }
7080
7081 /* The following function adds vector VECT to table TAB as its line
7082 with number VECT_NUM. */
7083 static void
7084 add_vect (state_ainsn_table_t tab, int vect_num, vla_hwint_t vect)
7085 {
7086 int vect_length;
7087 size_t real_vect_length;
7088 int comb_vect_index;
7089 int comb_vect_els_num;
7090 int vect_index;
7091 int first_unempty_vect_index;
7092 int additional_els_num;
7093 int no_state_value;
7094 vect_el_t vect_el;
7095 int i;
7096 unsigned long vect_mask, comb_vect_mask;
7097
7098 vect_length = VEC_length (vect_el_t, vect);
7099 gcc_assert (vect_length);
7100 gcc_assert (VEC_last (vect_el_t, vect) != undefined_vect_el_value);
7101 real_vect_length = tab->automaton->insn_equiv_classes_num;
7102 /* Form full vector in the table: */
7103 {
7104 size_t full_base = tab->automaton->insn_equiv_classes_num * vect_num;
7105 if (VEC_length (vect_el_t, tab->full_vect) < full_base + vect_length)
7106 VEC_safe_grow (vect_el_t,heap, tab->full_vect,
7107 full_base + vect_length);
7108 for (i = 0; i < vect_length; i++)
7109 VEC_replace (vect_el_t, tab->full_vect, full_base + i,
7110 VEC_index (vect_el_t, vect, i));
7111 }
7112 /* Form comb vector in the table: */
7113 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7114 == VEC_length (vect_el_t, tab->check_vect));
7115
7116 comb_vect_els_num = VEC_length (vect_el_t, tab->comb_vect);
7117 for (first_unempty_vect_index = 0;
7118 first_unempty_vect_index < vect_length;
7119 first_unempty_vect_index++)
7120 if (VEC_index (vect_el_t, vect, first_unempty_vect_index)
7121 != undefined_vect_el_value)
7122 break;
7123
7124 /* Search for the place in comb vect for the inserted vect. */
7125
7126 /* Slow case. */
7127 if (vect_length - first_unempty_vect_index >= SIZEOF_LONG * CHAR_BIT)
7128 {
7129 for (comb_vect_index = 0;
7130 comb_vect_index < comb_vect_els_num;
7131 comb_vect_index++)
7132 {
7133 for (vect_index = first_unempty_vect_index;
7134 vect_index < vect_length
7135 && vect_index + comb_vect_index < comb_vect_els_num;
7136 vect_index++)
7137 if (VEC_index (vect_el_t, vect, vect_index)
7138 != undefined_vect_el_value
7139 && (VEC_index (vect_el_t, tab->comb_vect,
7140 vect_index + comb_vect_index)
7141 != undefined_vect_el_value))
7142 break;
7143 if (vect_index >= vect_length
7144 || vect_index + comb_vect_index >= comb_vect_els_num)
7145 break;
7146 }
7147 goto found;
7148 }
7149
7150 /* Fast case. */
7151 vect_mask = 0;
7152 for (vect_index = first_unempty_vect_index;
7153 vect_index < vect_length;
7154 vect_index++)
7155 {
7156 vect_mask = vect_mask << 1;
7157 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7158 vect_mask |= 1;
7159 }
7160
7161 /* Search for the place in comb vect for the inserted vect. */
7162 comb_vect_index = 0;
7163 if (comb_vect_els_num == 0)
7164 goto found;
7165
7166 comb_vect_mask = 0;
7167 for (vect_index = first_unempty_vect_index;
7168 vect_index < vect_length && vect_index < comb_vect_els_num;
7169 vect_index++)
7170 {
7171 comb_vect_mask <<= 1;
7172 if (vect_index + comb_vect_index < comb_vect_els_num
7173 && VEC_index (vect_el_t, tab->comb_vect, vect_index + comb_vect_index)
7174 != undefined_vect_el_value)
7175 comb_vect_mask |= 1;
7176 }
7177 if ((vect_mask & comb_vect_mask) == 0)
7178 goto found;
7179
7180 for (comb_vect_index = 1, i = vect_length; i < comb_vect_els_num;
7181 comb_vect_index++, i++)
7182 {
7183 comb_vect_mask = (comb_vect_mask << 1) | 1;
7184 comb_vect_mask ^= (VEC_index (vect_el_t, tab->comb_vect, i)
7185 == undefined_vect_el_value);
7186 if ((vect_mask & comb_vect_mask) == 0)
7187 goto found;
7188 }
7189 for ( ; comb_vect_index < comb_vect_els_num; comb_vect_index++)
7190 {
7191 comb_vect_mask <<= 1;
7192 if ((vect_mask & comb_vect_mask) == 0)
7193 goto found;
7194 }
7195
7196 found:
7197 /* Slot was found. */
7198 additional_els_num = comb_vect_index + real_vect_length - comb_vect_els_num;
7199 if (additional_els_num < 0)
7200 additional_els_num = 0;
7201 /* Expand comb and check vectors. */
7202 vect_el = undefined_vect_el_value;
7203 no_state_value = tab->automaton->achieved_states_num;
7204 while (additional_els_num > 0)
7205 {
7206 VEC_safe_push (vect_el_t,heap, tab->comb_vect, vect_el);
7207 VEC_safe_push (vect_el_t,heap, tab->check_vect, no_state_value);
7208 additional_els_num--;
7209 }
7210 gcc_assert (VEC_length (vect_el_t, tab->comb_vect)
7211 >= comb_vect_index + real_vect_length);
7212 /* Fill comb and check vectors. */
7213 for (vect_index = 0; vect_index < vect_length; vect_index++)
7214 if (VEC_index (vect_el_t, vect, vect_index) != undefined_vect_el_value)
7215 {
7216 vect_el_t x = VEC_index (vect_el_t, vect, vect_index);
7217 gcc_assert (VEC_index (vect_el_t, tab->comb_vect,
7218 comb_vect_index + vect_index)
7219 == undefined_vect_el_value);
7220 gcc_assert (x >= 0);
7221 if (tab->max_comb_vect_el_value < x)
7222 tab->max_comb_vect_el_value = x;
7223 if (tab->min_comb_vect_el_value > x)
7224 tab->min_comb_vect_el_value = x;
7225 VEC_replace (vect_el_t, tab->comb_vect,
7226 comb_vect_index + vect_index, x);
7227 VEC_replace (vect_el_t, tab->check_vect,
7228 comb_vect_index + vect_index, vect_num);
7229 }
7230 if (tab->max_comb_vect_el_value < undefined_vect_el_value)
7231 tab->max_comb_vect_el_value = undefined_vect_el_value;
7232 if (tab->min_comb_vect_el_value > undefined_vect_el_value)
7233 tab->min_comb_vect_el_value = undefined_vect_el_value;
7234 if (tab->max_base_vect_el_value < comb_vect_index)
7235 tab->max_base_vect_el_value = comb_vect_index;
7236 if (tab->min_base_vect_el_value > comb_vect_index)
7237 tab->min_base_vect_el_value = comb_vect_index;
7238
7239 VEC_replace (vect_el_t, tab->base_vect, vect_num, comb_vect_index);
7240 }
7241
7242 /* Return number of out arcs of STATE. */
7243 static int
7244 out_state_arcs_num (const_state_t state)
7245 {
7246 int result;
7247 arc_t arc;
7248
7249 result = 0;
7250 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7251 {
7252 gcc_assert (arc->insn);
7253 if (arc->insn->first_ainsn_with_given_equivalence_num)
7254 result++;
7255 }
7256 return result;
7257 }
7258
7259 /* Compare number of possible transitions from the states. */
7260 static int
7261 compare_transition_els_num (const void *state_ptr_1,
7262 const void *state_ptr_2)
7263 {
7264 const int transition_els_num_1
7265 = out_state_arcs_num (*(const_state_t const*) state_ptr_1);
7266 const int transition_els_num_2
7267 = out_state_arcs_num (*(const_state_t const*) state_ptr_2);
7268
7269 if (transition_els_num_1 < transition_els_num_2)
7270 return 1;
7271 else if (transition_els_num_1 == transition_els_num_2)
7272 return 0;
7273 else
7274 return -1;
7275 }
7276
7277 /* The function adds element EL_VALUE to vector VECT for a table state
7278 x AINSN. */
7279 static void
7280 add_vect_el (vla_hwint_t *vect, ainsn_t ainsn, int el_value)
7281 {
7282 int equiv_class_num;
7283 int vect_index;
7284
7285 gcc_assert (ainsn);
7286 equiv_class_num = ainsn->insn_equiv_class_num;
7287 for (vect_index = VEC_length (vect_el_t, *vect);
7288 vect_index <= equiv_class_num;
7289 vect_index++)
7290 VEC_safe_push (vect_el_t,heap, *vect, undefined_vect_el_value);
7291 VEC_replace (vect_el_t, *vect, equiv_class_num, el_value);
7292 }
7293
7294 /* This is for forming vector of states of an automaton. */
7295 static VEC(state_t,heap) *output_states_vect;
7296
7297 /* The function is called by function pass_states. The function adds
7298 STATE to `output_states_vect'. */
7299 static void
7300 add_states_vect_el (state_t state)
7301 {
7302 VEC_safe_push (state_t,heap, output_states_vect, state);
7303 }
7304
7305 /* Form and output vectors (comb, check, base or full vector)
7306 representing transition table of AUTOMATON. */
7307 static void
7308 output_trans_table (automaton_t automaton)
7309 {
7310 size_t i;
7311 arc_t arc;
7312 vla_hwint_t transition_vect = 0;
7313
7314 undefined_vect_el_value = automaton->achieved_states_num;
7315 automaton->trans_table = create_state_ainsn_table (automaton);
7316 /* Create vect of pointers to states ordered by num of transitions
7317 from the state (state with the maximum num is the first). */
7318 output_states_vect = 0;
7319 pass_states (automaton, add_states_vect_el);
7320 qsort (VEC_address (state_t, output_states_vect),
7321 VEC_length (state_t, output_states_vect),
7322 sizeof (state_t), compare_transition_els_num);
7323
7324 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7325 {
7326 VEC_truncate (vect_el_t, transition_vect, 0);
7327 for (arc = first_out_arc (VEC_index (state_t, output_states_vect, i));
7328 arc != NULL;
7329 arc = next_out_arc (arc))
7330 {
7331 gcc_assert (arc->insn);
7332 if (arc->insn->first_ainsn_with_given_equivalence_num)
7333 add_vect_el (&transition_vect, arc->insn,
7334 arc->to_state->order_state_num);
7335 }
7336 add_vect (automaton->trans_table,
7337 VEC_index (state_t, output_states_vect, i)->order_state_num,
7338 transition_vect);
7339 }
7340 output_state_ainsn_table
7341 (automaton->trans_table, "state transitions",
7342 output_trans_full_vect_name, output_trans_comb_vect_name,
7343 output_trans_check_vect_name, output_trans_base_vect_name);
7344
7345 VEC_free (state_t,heap, output_states_vect);
7346 VEC_free (vect_el_t,heap, transition_vect);
7347 }
7348
7349 /* The current number of passing states to find minimal issue delay
7350 value for an ainsn and state. */
7351 static int curr_state_pass_num;
7352
7353 /* This recursive function passes states to find minimal issue delay
7354 value for AINSN. The state being visited is STATE. The function
7355 returns minimal issue delay value for AINSN in STATE or -1 if we
7356 enter into a loop. */
7357 static int
7358 min_issue_delay_pass_states (state_t state, ainsn_t ainsn)
7359 {
7360 arc_t arc;
7361 int min_insn_issue_delay, insn_issue_delay;
7362
7363 if (state->state_pass_num == curr_state_pass_num
7364 || state->min_insn_issue_delay != -1)
7365 /* We've entered into a loop or already have the correct value for
7366 given state and ainsn. */
7367 return state->min_insn_issue_delay;
7368 state->state_pass_num = curr_state_pass_num;
7369 min_insn_issue_delay = -1;
7370 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
7371 if (arc->insn == ainsn)
7372 {
7373 min_insn_issue_delay = 0;
7374 break;
7375 }
7376 else
7377 {
7378 insn_issue_delay = min_issue_delay_pass_states (arc->to_state, ainsn);
7379 if (insn_issue_delay != -1)
7380 {
7381 if (arc->insn->insn_reserv_decl
7382 == DECL_INSN_RESERV (advance_cycle_insn_decl))
7383 insn_issue_delay++;
7384 if (min_insn_issue_delay == -1
7385 || min_insn_issue_delay > insn_issue_delay)
7386 {
7387 min_insn_issue_delay = insn_issue_delay;
7388 if (insn_issue_delay == 0)
7389 break;
7390 }
7391 }
7392 }
7393 return min_insn_issue_delay;
7394 }
7395
7396 /* The function searches minimal issue delay value for AINSN in STATE.
7397 The function can return negative value if we can not issue AINSN. We
7398 will report about it later. */
7399 static int
7400 min_issue_delay (state_t state, ainsn_t ainsn)
7401 {
7402 curr_state_pass_num++;
7403 state->min_insn_issue_delay = min_issue_delay_pass_states (state, ainsn);
7404 return state->min_insn_issue_delay;
7405 }
7406
7407 /* The function initiates code for finding minimal issue delay values.
7408 It should be called only once. */
7409 static void
7410 initiate_min_issue_delay_pass_states (void)
7411 {
7412 curr_state_pass_num = 0;
7413 }
7414
7415 /* Form and output vectors representing minimal issue delay table of
7416 AUTOMATON. The table is state x ainsn -> minimal issue delay of
7417 the ainsn. */
7418 static void
7419 output_min_issue_delay_table (automaton_t automaton)
7420 {
7421 vla_hwint_t min_issue_delay_vect;
7422 vla_hwint_t compressed_min_issue_delay_vect;
7423 vect_el_t min_delay;
7424 ainsn_t ainsn;
7425 size_t i, min_issue_delay_len;
7426 size_t compressed_min_issue_delay_len;
7427 size_t cfactor;
7428
7429 /* Create vect of pointers to states ordered by num of transitions
7430 from the state (state with the maximum num is the first). */
7431 output_states_vect = 0;
7432 pass_states (automaton, add_states_vect_el);
7433
7434 min_issue_delay_len = (VEC_length (state_t, output_states_vect)
7435 * automaton->insn_equiv_classes_num);
7436 min_issue_delay_vect = VEC_alloc (vect_el_t,heap, min_issue_delay_len);
7437 for (i = 0; i < min_issue_delay_len; i++)
7438 VEC_quick_push (vect_el_t, min_issue_delay_vect, 0);
7439
7440 automaton->max_min_delay = 0;
7441 for (ainsn = automaton->ainsn_list; ainsn != NULL; ainsn = ainsn->next_ainsn)
7442 if (ainsn->first_ainsn_with_given_equivalence_num)
7443 {
7444 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7445 VEC_index (state_t, output_states_vect, i)->min_insn_issue_delay = -1;
7446 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7447 {
7448 state_t s = VEC_index (state_t, output_states_vect, i);
7449 min_delay = min_issue_delay (s, ainsn);
7450 if (automaton->max_min_delay < min_delay)
7451 automaton->max_min_delay = min_delay;
7452 VEC_replace (vect_el_t, min_issue_delay_vect,
7453 s->order_state_num
7454 * automaton->insn_equiv_classes_num
7455 + ainsn->insn_equiv_class_num,
7456 min_delay);
7457 }
7458 }
7459 fprintf (output_file, "/* Vector of min issue delay of insns. */\n");
7460 fprintf (output_file, "static const ");
7461 output_range_type (output_file, 0, automaton->max_min_delay);
7462 fprintf (output_file, " ");
7463 output_min_issue_delay_vect_name (output_file, automaton);
7464 fprintf (output_file, "[] ATTRIBUTE_UNUSED = {\n");
7465 /* Compress the vector. */
7466 if (automaton->max_min_delay < 2)
7467 cfactor = 8;
7468 else if (automaton->max_min_delay < 4)
7469 cfactor = 4;
7470 else if (automaton->max_min_delay < 16)
7471 cfactor = 2;
7472 else
7473 cfactor = 1;
7474 automaton->min_issue_delay_table_compression_factor = cfactor;
7475
7476 compressed_min_issue_delay_len = (min_issue_delay_len+cfactor-1) / cfactor;
7477 compressed_min_issue_delay_vect
7478 = VEC_alloc (vect_el_t,heap, compressed_min_issue_delay_len);
7479
7480 for (i = 0; i < compressed_min_issue_delay_len; i++)
7481 VEC_quick_push (vect_el_t, compressed_min_issue_delay_vect, 0);
7482
7483 for (i = 0; i < min_issue_delay_len; i++)
7484 {
7485 size_t ci = i / cfactor;
7486 vect_el_t x = VEC_index (vect_el_t, min_issue_delay_vect, i);
7487 vect_el_t cx = VEC_index (vect_el_t, compressed_min_issue_delay_vect, ci);
7488
7489 cx |= x << (8 - (i % cfactor + 1) * (8 / cfactor));
7490 VEC_replace (vect_el_t, compressed_min_issue_delay_vect, ci, cx);
7491 }
7492 output_vect (compressed_min_issue_delay_vect);
7493 fprintf (output_file, "};\n\n");
7494 VEC_free (state_t,heap, output_states_vect);
7495 VEC_free (vect_el_t,heap, min_issue_delay_vect);
7496 VEC_free (vect_el_t,heap, compressed_min_issue_delay_vect);
7497 }
7498
7499 /* Form and output vector representing the locked states of
7500 AUTOMATON. */
7501 static void
7502 output_dead_lock_vect (automaton_t automaton)
7503 {
7504 size_t i;
7505 arc_t arc;
7506 vla_hwint_t dead_lock_vect = 0;
7507
7508 /* Create vect of pointers to states ordered by num of
7509 transitions from the state (state with the maximum num is the
7510 first). */
7511 automaton->locked_states = 0;
7512 output_states_vect = 0;
7513 pass_states (automaton, add_states_vect_el);
7514
7515 VEC_safe_grow (vect_el_t,heap, dead_lock_vect,
7516 VEC_length (state_t, output_states_vect));
7517 for (i = 0; i < VEC_length (state_t, output_states_vect); i++)
7518 {
7519 state_t s = VEC_index (state_t, output_states_vect, i);
7520 arc = first_out_arc (s);
7521 gcc_assert (arc);
7522 if (next_out_arc (arc) == NULL
7523 && (arc->insn->insn_reserv_decl
7524 == DECL_INSN_RESERV (advance_cycle_insn_decl)))
7525 {
7526 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 1);
7527 automaton->locked_states++;
7528 }
7529 else
7530 VEC_replace (vect_el_t, dead_lock_vect, s->order_state_num, 0);
7531 }
7532 if (automaton->locked_states == 0)
7533 return;
7534
7535 fprintf (output_file, "/* Vector for locked state flags. */\n");
7536 fprintf (output_file, "static const ");
7537 output_range_type (output_file, 0, 1);
7538 fprintf (output_file, " ");
7539 output_dead_lock_vect_name (output_file, automaton);
7540 fprintf (output_file, "[] = {\n");
7541 output_vect (dead_lock_vect);
7542 fprintf (output_file, "};\n\n");
7543 VEC_free (state_t,heap, output_states_vect);
7544 VEC_free (vect_el_t,heap, dead_lock_vect);
7545 }
7546
7547 /* Form and output vector representing reserved units of the states of
7548 AUTOMATON. */
7549 static void
7550 output_reserved_units_table (automaton_t automaton)
7551 {
7552 vla_hwint_t reserved_units_table = 0;
7553 int state_byte_size;
7554 int reserved_units_size;
7555 size_t n;
7556 int i;
7557
7558 if (description->query_units_num == 0)
7559 return;
7560
7561 /* Create vect of pointers to states. */
7562 output_states_vect = 0;
7563 pass_states (automaton, add_states_vect_el);
7564 /* Create vector. */
7565 state_byte_size = (description->query_units_num + 7) / 8;
7566 reserved_units_size = (VEC_length (state_t, output_states_vect)
7567 * state_byte_size);
7568
7569 reserved_units_table = VEC_alloc (vect_el_t,heap, reserved_units_size);
7570
7571 for (i = 0; i < reserved_units_size; i++)
7572 VEC_quick_push (vect_el_t, reserved_units_table, 0);
7573 for (n = 0; n < VEC_length (state_t, output_states_vect); n++)
7574 {
7575 state_t s = VEC_index (state_t, output_states_vect, n);
7576 for (i = 0; i < description->units_num; i++)
7577 if (units_array [i]->query_p
7578 && first_cycle_unit_presence (s, i))
7579 {
7580 int ri = (s->order_state_num * state_byte_size
7581 + units_array [i]->query_num / 8);
7582 vect_el_t x = VEC_index (vect_el_t, reserved_units_table, ri);
7583
7584 x += 1 << (units_array [i]->query_num % 8);
7585 VEC_replace (vect_el_t, reserved_units_table, ri, x);
7586 }
7587 }
7588 fprintf (output_file, "\n#if %s\n", CPU_UNITS_QUERY_MACRO_NAME);
7589 fprintf (output_file, "/* Vector for reserved units of states. */\n");
7590 fprintf (output_file, "static const ");
7591 output_range_type (output_file, 0, 255);
7592 fprintf (output_file, " ");
7593 output_reserved_units_table_name (output_file, automaton);
7594 fprintf (output_file, "[] = {\n");
7595 output_vect (reserved_units_table);
7596 fprintf (output_file, "};\n#endif /* #if %s */\n\n",
7597 CPU_UNITS_QUERY_MACRO_NAME);
7598
7599 VEC_free (state_t,heap, output_states_vect);
7600 VEC_free (vect_el_t,heap, reserved_units_table);
7601 }
7602
7603 /* The function outputs all tables representing DFA(s) used for fast
7604 pipeline hazards recognition. */
7605 static void
7606 output_tables (void)
7607 {
7608 automaton_t automaton;
7609
7610 initiate_min_issue_delay_pass_states ();
7611 for (automaton = description->first_automaton;
7612 automaton != NULL;
7613 automaton = automaton->next_automaton)
7614 {
7615 output_translate_vect (automaton);
7616 output_trans_table (automaton);
7617 output_min_issue_delay_table (automaton);
7618 output_dead_lock_vect (automaton);
7619 output_reserved_units_table (automaton);
7620 }
7621 fprintf (output_file, "\n#define %s %d\n\n", ADVANCE_CYCLE_VALUE_NAME,
7622 DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
7623 }
7624
7625 /* The function outputs definition and value of PHR interface variable
7626 `max_insn_queue_index'. Its value is not less than maximal queue
7627 length needed for the insn scheduler. */
7628 static void
7629 output_max_insn_queue_index_def (void)
7630 {
7631 int i, max, latency;
7632 decl_t decl;
7633
7634 max = description->max_insn_reserv_cycles;
7635 for (i = 0; i < description->decls_num; i++)
7636 {
7637 decl = description->decls [i];
7638 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
7639 {
7640 latency = DECL_INSN_RESERV (decl)->default_latency;
7641 if (latency > max)
7642 max = latency;
7643 }
7644 else if (decl->mode == dm_bypass)
7645 {
7646 latency = DECL_BYPASS (decl)->latency;
7647 if (latency > max)
7648 max = latency;
7649 }
7650 }
7651 for (i = 0; (1 << i) <= max; i++)
7652 ;
7653 gcc_assert (i >= 0);
7654 fprintf (output_file, "\nconst int max_insn_queue_index = %d;\n\n",
7655 (1 << i) - 1);
7656 }
7657
7658 /* The function outputs switch cases for insn reservations using
7659 function *output_automata_list_code. */
7660 static void
7661 output_insn_code_cases (void (*output_automata_list_code)
7662 (automata_list_el_t))
7663 {
7664 decl_t decl, decl2;
7665 int i, j;
7666
7667 for (i = 0; i < description->decls_num; i++)
7668 {
7669 decl = description->decls [i];
7670 if (decl->mode == dm_insn_reserv)
7671 DECL_INSN_RESERV (decl)->processed_p = FALSE;
7672 }
7673 for (i = 0; i < description->decls_num; i++)
7674 {
7675 decl = description->decls [i];
7676 if (decl->mode == dm_insn_reserv
7677 && !DECL_INSN_RESERV (decl)->processed_p)
7678 {
7679 for (j = i; j < description->decls_num; j++)
7680 {
7681 decl2 = description->decls [j];
7682 if (decl2->mode == dm_insn_reserv
7683 && (DECL_INSN_RESERV (decl2)->important_automata_list
7684 == DECL_INSN_RESERV (decl)->important_automata_list))
7685 {
7686 DECL_INSN_RESERV (decl2)->processed_p = TRUE;
7687 fprintf (output_file, " case %d: /* %s */\n",
7688 DECL_INSN_RESERV (decl2)->insn_num,
7689 DECL_INSN_RESERV (decl2)->name);
7690 }
7691 }
7692 (*output_automata_list_code)
7693 (DECL_INSN_RESERV (decl)->important_automata_list);
7694 }
7695 }
7696 }
7697
7698
7699 /* The function outputs a code for evaluation of a minimal delay of
7700 issue of insns which have reservations in given AUTOMATA_LIST. */
7701 static void
7702 output_automata_list_min_issue_delay_code (automata_list_el_t automata_list)
7703 {
7704 automata_list_el_t el;
7705 automaton_t automaton;
7706
7707 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7708 {
7709 automaton = el->automaton;
7710 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7711 output_min_issue_delay_vect_name (output_file, automaton);
7712 fprintf (output_file,
7713 (automaton->min_issue_delay_table_compression_factor != 1
7714 ? " [(" : " ["));
7715 output_translate_vect_name (output_file, automaton);
7716 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7717 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7718 output_chip_member_name (output_file, automaton);
7719 fprintf (output_file, " * %d", automaton->insn_equiv_classes_num);
7720 if (automaton->min_issue_delay_table_compression_factor == 1)
7721 fprintf (output_file, "];\n");
7722 else
7723 {
7724 fprintf (output_file, ") / %d];\n",
7725 automaton->min_issue_delay_table_compression_factor);
7726 fprintf (output_file, " %s = (%s >> (8 - (",
7727 TEMPORARY_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7728 output_translate_vect_name (output_file, automaton);
7729 fprintf
7730 (output_file, " [%s] %% %d + 1) * %d)) & %d;\n",
7731 INTERNAL_INSN_CODE_NAME,
7732 automaton->min_issue_delay_table_compression_factor,
7733 8 / automaton->min_issue_delay_table_compression_factor,
7734 (1 << (8 / automaton->min_issue_delay_table_compression_factor))
7735 - 1);
7736 }
7737 if (el == automata_list)
7738 fprintf (output_file, " %s = %s;\n",
7739 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7740 else
7741 {
7742 fprintf (output_file, " if (%s > %s)\n",
7743 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7744 fprintf (output_file, " %s = %s;\n",
7745 RESULT_VARIABLE_NAME, TEMPORARY_VARIABLE_NAME);
7746 }
7747 }
7748 fprintf (output_file, " break;\n\n");
7749 }
7750
7751 /* Output function `internal_min_issue_delay'. */
7752 static void
7753 output_internal_min_issue_delay_func (void)
7754 {
7755 fprintf (output_file,
7756 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7757 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7758 CHIP_NAME, CHIP_PARAMETER_NAME);
7759 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n int %s = -1;\n",
7760 TEMPORARY_VARIABLE_NAME, RESULT_VARIABLE_NAME);
7761 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7762 output_insn_code_cases (output_automata_list_min_issue_delay_code);
7763 fprintf (output_file,
7764 "\n default:\n %s = -1;\n break;\n }\n",
7765 RESULT_VARIABLE_NAME);
7766 fprintf (output_file, " return %s;\n", RESULT_VARIABLE_NAME);
7767 fprintf (output_file, "}\n\n");
7768 }
7769
7770 /* The function outputs a code changing state after issue of insns
7771 which have reservations in given AUTOMATA_LIST. */
7772 static void
7773 output_automata_list_transition_code (automata_list_el_t automata_list)
7774 {
7775 automata_list_el_t el, next_el;
7776
7777 fprintf (output_file, " {\n");
7778 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7779 for (el = automata_list;; el = next_el)
7780 {
7781 next_el = el->next_automata_list_el;
7782 if (next_el == NULL)
7783 break;
7784 fprintf (output_file, " ");
7785 output_state_member_type (output_file, el->automaton);
7786 fprintf (output_file, " ");
7787 output_temp_chip_member_name (output_file, el->automaton);
7788 fprintf (output_file, ";\n");
7789 }
7790 for (el = automata_list; el != NULL; el = el->next_automata_list_el)
7791 if (comb_vect_p (el->automaton->trans_table))
7792 {
7793 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7794 output_trans_base_vect_name (output_file, el->automaton);
7795 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
7796 output_chip_member_name (output_file, el->automaton);
7797 fprintf (output_file, "] + ");
7798 output_translate_vect_name (output_file, el->automaton);
7799 fprintf (output_file, " [%s];\n", INTERNAL_INSN_CODE_NAME);
7800 fprintf (output_file, " if (");
7801 output_trans_check_vect_name (output_file, el->automaton);
7802 fprintf (output_file, " [%s] != %s->",
7803 TEMPORARY_VARIABLE_NAME, CHIP_PARAMETER_NAME);
7804 output_chip_member_name (output_file, el->automaton);
7805 fprintf (output_file, ")\n");
7806 fprintf (output_file, " return %s (%s, %s);\n",
7807 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7808 CHIP_PARAMETER_NAME);
7809 fprintf (output_file, " else\n");
7810 fprintf (output_file, " ");
7811 if (el->next_automata_list_el != NULL)
7812 output_temp_chip_member_name (output_file, el->automaton);
7813 else
7814 {
7815 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7816 output_chip_member_name (output_file, el->automaton);
7817 }
7818 fprintf (output_file, " = ");
7819 output_trans_comb_vect_name (output_file, el->automaton);
7820 fprintf (output_file, " [%s];\n", TEMPORARY_VARIABLE_NAME);
7821 }
7822 else
7823 {
7824 fprintf (output_file, "\n %s = ", TEMPORARY_VARIABLE_NAME);
7825 output_trans_full_vect_name (output_file, el->automaton);
7826 fprintf (output_file, " [");
7827 output_translate_vect_name (output_file, el->automaton);
7828 fprintf (output_file, " [%s] + ", INTERNAL_INSN_CODE_NAME);
7829 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7830 output_chip_member_name (output_file, el->automaton);
7831 fprintf (output_file, " * %d];\n",
7832 el->automaton->insn_equiv_classes_num);
7833 fprintf (output_file, " if (%s >= %d)\n",
7834 TEMPORARY_VARIABLE_NAME, el->automaton->achieved_states_num);
7835 fprintf (output_file, " return %s (%s, %s);\n",
7836 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7837 CHIP_PARAMETER_NAME);
7838 fprintf (output_file, " else\n ");
7839 if (el->next_automata_list_el != NULL)
7840 output_temp_chip_member_name (output_file, el->automaton);
7841 else
7842 {
7843 fprintf (output_file, "%s->", CHIP_PARAMETER_NAME);
7844 output_chip_member_name (output_file, el->automaton);
7845 }
7846 fprintf (output_file, " = %s;\n", TEMPORARY_VARIABLE_NAME);
7847 }
7848 if (automata_list != NULL && automata_list->next_automata_list_el != NULL)
7849 for (el = automata_list;; el = next_el)
7850 {
7851 next_el = el->next_automata_list_el;
7852 if (next_el == NULL)
7853 break;
7854 fprintf (output_file, " %s->", CHIP_PARAMETER_NAME);
7855 output_chip_member_name (output_file, el->automaton);
7856 fprintf (output_file, " = ");
7857 output_temp_chip_member_name (output_file, el->automaton);
7858 fprintf (output_file, ";\n");
7859 }
7860 fprintf (output_file, " return -1;\n");
7861 fprintf (output_file, " }\n");
7862 }
7863
7864 /* Output function `internal_state_transition'. */
7865 static void
7866 output_internal_trans_func (void)
7867 {
7868 fprintf (output_file,
7869 "static int\n%s (int %s, struct %s *%s ATTRIBUTE_UNUSED)\n",
7870 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7871 CHIP_NAME, CHIP_PARAMETER_NAME);
7872 fprintf (output_file, "{\n int %s ATTRIBUTE_UNUSED;\n", TEMPORARY_VARIABLE_NAME);
7873 fprintf (output_file, "\n switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
7874 output_insn_code_cases (output_automata_list_transition_code);
7875 fprintf (output_file, "\n default:\n return -1;\n }\n");
7876 fprintf (output_file, "}\n\n");
7877 }
7878
7879 /* Output code
7880
7881 if (insn != 0)
7882 {
7883 insn_code = dfa_insn_code (insn);
7884 if (insn_code > DFA__ADVANCE_CYCLE)
7885 return code;
7886 }
7887 else
7888 insn_code = DFA__ADVANCE_CYCLE;
7889
7890 where insn denotes INSN_NAME, insn_code denotes INSN_CODE_NAME, and
7891 code denotes CODE. */
7892 static void
7893 output_internal_insn_code_evaluation (const char *insn_name,
7894 const char *insn_code_name,
7895 int code)
7896 {
7897 fprintf (output_file, "\n if (%s != 0)\n {\n", insn_name);
7898 fprintf (output_file, " %s = %s (%s);\n", insn_code_name,
7899 DFA_INSN_CODE_FUNC_NAME, insn_name);
7900 fprintf (output_file, " if (%s > %s)\n return %d;\n",
7901 insn_code_name, ADVANCE_CYCLE_VALUE_NAME, code);
7902 fprintf (output_file, " }\n else\n %s = %s;\n\n",
7903 insn_code_name, ADVANCE_CYCLE_VALUE_NAME);
7904 }
7905
7906
7907 /* This function outputs `dfa_insn_code' and its helper function
7908 `dfa_insn_code_enlarge'. */
7909 static void
7910 output_dfa_insn_code_func (void)
7911 {
7912 /* Emacs c-mode gets really confused if there's a { or } in column 0
7913 inside a string, so don't do that. */
7914 fprintf (output_file, "\
7915 static void\n\
7916 dfa_insn_code_enlarge (int uid)\n\
7917 {\n\
7918 int i = %s;\n\
7919 %s = 2 * uid;\n\
7920 %s = XRESIZEVEC (int, %s,\n\
7921 %s);\n\
7922 for (; i < %s; i++)\n\
7923 %s[i] = -1;\n}\n\n",
7924 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7925 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7926 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
7927 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7928 DFA_INSN_CODES_LENGTH_VARIABLE_NAME,
7929 DFA_INSN_CODES_VARIABLE_NAME);
7930 fprintf (output_file, "\
7931 static inline int\n%s (rtx %s)\n\
7932 {\n\
7933 int uid = INSN_UID (%s);\n\
7934 int %s;\n\n",
7935 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7936 INSN_PARAMETER_NAME, INTERNAL_INSN_CODE_NAME);
7937
7938 fprintf (output_file,
7939 " if (uid >= %s)\n dfa_insn_code_enlarge (uid);\n\n",
7940 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
7941 fprintf (output_file, " %s = %s[uid];\n",
7942 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODES_VARIABLE_NAME);
7943 fprintf (output_file, "\
7944 if (%s < 0)\n\
7945 {\n\
7946 %s = %s (%s);\n\
7947 %s[uid] = %s;\n\
7948 }\n",
7949 INTERNAL_INSN_CODE_NAME,
7950 INTERNAL_INSN_CODE_NAME,
7951 INTERNAL_DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME,
7952 DFA_INSN_CODES_VARIABLE_NAME, INTERNAL_INSN_CODE_NAME);
7953 fprintf (output_file, " return %s;\n}\n\n", INTERNAL_INSN_CODE_NAME);
7954 }
7955
7956 /* The function outputs PHR interface function `state_transition'. */
7957 static void
7958 output_trans_func (void)
7959 {
7960 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7961 TRANSITION_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7962 INSN_PARAMETER_NAME);
7963 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7964 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
7965 INTERNAL_INSN_CODE_NAME, -1);
7966 fprintf (output_file, " return %s (%s, (struct %s *) %s);\n}\n\n",
7967 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME, STATE_NAME);
7968 }
7969
7970 /* Output function `min_issue_delay'. */
7971 static void
7972 output_min_issue_delay_func (void)
7973 {
7974 fprintf (output_file, "int\n%s (%s %s, rtx %s)\n",
7975 MIN_ISSUE_DELAY_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME,
7976 INSN_PARAMETER_NAME);
7977 fprintf (output_file, "{\n int %s;\n", INTERNAL_INSN_CODE_NAME);
7978 fprintf (output_file, "\n if (%s != 0)\n {\n", INSN_PARAMETER_NAME);
7979 fprintf (output_file, " %s = %s (%s);\n", INTERNAL_INSN_CODE_NAME,
7980 DFA_INSN_CODE_FUNC_NAME, INSN_PARAMETER_NAME);
7981 fprintf (output_file, " if (%s > %s)\n return 0;\n",
7982 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7983 fprintf (output_file, " }\n else\n %s = %s;\n",
7984 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
7985 fprintf (output_file, "\n return %s (%s, (struct %s *) %s);\n",
7986 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
7987 CHIP_NAME, STATE_NAME);
7988 fprintf (output_file, "}\n\n");
7989 }
7990
7991 /* Output function `internal_dead_lock'. */
7992 static void
7993 output_internal_dead_lock_func (void)
7994 {
7995 automaton_t automaton;
7996
7997 fprintf (output_file, "static int\n%s (struct %s *ARG_UNUSED (%s))\n",
7998 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
7999 fprintf (output_file, "{\n");
8000 for (automaton = description->first_automaton;
8001 automaton != NULL;
8002 automaton = automaton->next_automaton)
8003 if (automaton->locked_states)
8004 {
8005 fprintf (output_file, " if (");
8006 output_dead_lock_vect_name (output_file, automaton);
8007 fprintf (output_file, " [%s->", CHIP_PARAMETER_NAME);
8008 output_chip_member_name (output_file, automaton);
8009 fprintf (output_file, "])\n return 1/* TRUE */;\n");
8010 }
8011 fprintf (output_file, " return 0/* FALSE */;\n}\n\n");
8012 }
8013
8014 /* The function outputs PHR interface function `state_dead_lock_p'. */
8015 static void
8016 output_dead_lock_func (void)
8017 {
8018 fprintf (output_file, "int\n%s (%s %s)\n",
8019 DEAD_LOCK_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8020 fprintf (output_file, "{\n return %s ((struct %s *) %s);\n}\n\n",
8021 INTERNAL_DEAD_LOCK_FUNC_NAME, CHIP_NAME, STATE_NAME);
8022 }
8023
8024 /* Output function `internal_reset'. */
8025 static void
8026 output_internal_reset_func (void)
8027 {
8028 fprintf (output_file, "static inline void\n%s (struct %s *%s)\n",
8029 INTERNAL_RESET_FUNC_NAME, CHIP_NAME, CHIP_PARAMETER_NAME);
8030 fprintf (output_file, "{\n memset (%s, 0, sizeof (struct %s));\n}\n\n",
8031 CHIP_PARAMETER_NAME, CHIP_NAME);
8032 }
8033
8034 /* The function outputs PHR interface function `state_size'. */
8035 static void
8036 output_size_func (void)
8037 {
8038 fprintf (output_file, "int\n%s (void)\n", SIZE_FUNC_NAME);
8039 fprintf (output_file, "{\n return sizeof (struct %s);\n}\n\n", CHIP_NAME);
8040 }
8041
8042 /* The function outputs PHR interface function `state_reset'. */
8043 static void
8044 output_reset_func (void)
8045 {
8046 fprintf (output_file, "void\n%s (%s %s)\n",
8047 RESET_FUNC_NAME, STATE_TYPE_NAME, STATE_NAME);
8048 fprintf (output_file, "{\n %s ((struct %s *) %s);\n}\n\n", INTERNAL_RESET_FUNC_NAME,
8049 CHIP_NAME, STATE_NAME);
8050 }
8051
8052 /* Output function `min_insn_conflict_delay'. */
8053 static void
8054 output_min_insn_conflict_delay_func (void)
8055 {
8056 fprintf (output_file,
8057 "int\n%s (%s %s, rtx %s, rtx %s)\n",
8058 MIN_INSN_CONFLICT_DELAY_FUNC_NAME, STATE_TYPE_NAME,
8059 STATE_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8060 fprintf (output_file, "{\n struct %s %s;\n int %s, %s, transition;\n",
8061 CHIP_NAME, CHIP_NAME, INTERNAL_INSN_CODE_NAME,
8062 INTERNAL_INSN2_CODE_NAME);
8063 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8064 INTERNAL_INSN_CODE_NAME, 0);
8065 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8066 INTERNAL_INSN2_CODE_NAME, 0);
8067 fprintf (output_file, " memcpy (&%s, %s, sizeof (%s));\n",
8068 CHIP_NAME, STATE_NAME, CHIP_NAME);
8069 fprintf (output_file, " %s (&%s);\n", INTERNAL_RESET_FUNC_NAME, CHIP_NAME);
8070 fprintf (output_file, " transition = %s (%s, &%s);\n",
8071 INTERNAL_TRANSITION_FUNC_NAME, INTERNAL_INSN_CODE_NAME, CHIP_NAME);
8072 fprintf (output_file, " gcc_assert (transition <= 0);\n");
8073 fprintf (output_file, " return %s (%s, &%s);\n",
8074 INTERNAL_MIN_ISSUE_DELAY_FUNC_NAME, INTERNAL_INSN2_CODE_NAME,
8075 CHIP_NAME);
8076 fprintf (output_file, "}\n\n");
8077 }
8078
8079 /* Output the array holding default latency values. These are used in
8080 insn_latency and maximal_insn_latency function implementations. */
8081 static void
8082 output_default_latencies (void)
8083 {
8084 int i, j, col;
8085 decl_t decl;
8086 const char *tabletype = "unsigned char";
8087
8088 /* Find the smallest integer type that can hold all the default
8089 latency values. */
8090 for (i = 0; i < description->decls_num; i++)
8091 if (description->decls[i]->mode == dm_insn_reserv)
8092 {
8093 decl = description->decls[i];
8094 if (DECL_INSN_RESERV (decl)->default_latency > UCHAR_MAX
8095 && tabletype[0] != 'i') /* Don't shrink it. */
8096 tabletype = "unsigned short";
8097 if (DECL_INSN_RESERV (decl)->default_latency > USHRT_MAX)
8098 tabletype = "int";
8099 }
8100
8101 fprintf (output_file, " static const %s default_latencies[] =\n {",
8102 tabletype);
8103
8104 for (i = 0, j = 0, col = 7; i < description->decls_num; i++)
8105 if (description->decls[i]->mode == dm_insn_reserv
8106 && description->decls[i] != advance_cycle_insn_decl)
8107 {
8108 if ((col = (col+1) % 8) == 0)
8109 fputs ("\n ", output_file);
8110 decl = description->decls[i];
8111 gcc_assert (j++ == DECL_INSN_RESERV (decl)->insn_num);
8112 fprintf (output_file, "% 4d,",
8113 DECL_INSN_RESERV (decl)->default_latency);
8114 }
8115 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8116 fputs ("\n };\n", output_file);
8117 }
8118
8119 /* Output function `internal_insn_latency'. */
8120 static void
8121 output_internal_insn_latency_func (void)
8122 {
8123 int i;
8124 decl_t decl;
8125 struct bypass_decl *bypass;
8126
8127 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",
8128 INTERNAL_INSN_LATENCY_FUNC_NAME, INTERNAL_INSN_CODE_NAME,
8129 INTERNAL_INSN2_CODE_NAME, INSN_PARAMETER_NAME,
8130 INSN2_PARAMETER_NAME);
8131 fprintf (output_file, "{\n");
8132
8133 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8134 {
8135 fputs (" return 0;\n}\n\n", output_file);
8136 return;
8137 }
8138
8139 fprintf (output_file, " if (%s >= %s || %s >= %s)\n return 0;\n",
8140 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8141 INTERNAL_INSN2_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8142
8143 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8144 for (i = 0; i < description->decls_num; i++)
8145 if (description->decls[i]->mode == dm_insn_reserv
8146 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8147 {
8148 decl = description->decls [i];
8149 fprintf (output_file,
8150 " case %d:\n switch (%s)\n {\n",
8151 DECL_INSN_RESERV (decl)->insn_num,
8152 INTERNAL_INSN2_CODE_NAME);
8153 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8154 bypass != NULL;
8155 bypass = bypass->next)
8156 {
8157 gcc_assert (bypass->in_insn_reserv->insn_num
8158 != (DECL_INSN_RESERV
8159 (advance_cycle_insn_decl)->insn_num));
8160 fprintf (output_file, " case %d:\n",
8161 bypass->in_insn_reserv->insn_num);
8162 if (bypass->bypass_guard_name == NULL)
8163 fprintf (output_file, " return %d;\n",
8164 bypass->latency);
8165 else
8166 {
8167 fprintf (output_file,
8168 " if (%s (%s, %s))\n",
8169 bypass->bypass_guard_name, INSN_PARAMETER_NAME,
8170 INSN2_PARAMETER_NAME);
8171 fprintf (output_file,
8172 " return %d;\n break;\n",
8173 bypass->latency);
8174 }
8175 }
8176 fputs (" }\n break;\n", output_file);
8177 }
8178
8179 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8180 INTERNAL_INSN_CODE_NAME);
8181 }
8182
8183 /* Output function `internal_maximum_insn_latency'. */
8184 static void
8185 output_internal_maximal_insn_latency_func (void)
8186 {
8187 decl_t decl;
8188 struct bypass_decl *bypass;
8189 int i;
8190 int max;
8191
8192 fprintf (output_file, "static int\n%s (int %s ATTRIBUTE_UNUSED,\n\trtx %s ATTRIBUTE_UNUSED)\n",
8193 "internal_maximal_insn_latency", INTERNAL_INSN_CODE_NAME,
8194 INSN_PARAMETER_NAME);
8195 fprintf (output_file, "{\n");
8196
8197 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8198 {
8199 fputs (" return 0;\n}\n\n", output_file);
8200 return;
8201 }
8202
8203 fprintf (output_file, " switch (%s)\n {\n", INTERNAL_INSN_CODE_NAME);
8204 for (i = 0; i < description->decls_num; i++)
8205 if (description->decls[i]->mode == dm_insn_reserv
8206 && DECL_INSN_RESERV (description->decls[i])->bypass_list)
8207 {
8208 decl = description->decls [i];
8209 max = DECL_INSN_RESERV (decl)->default_latency;
8210 fprintf (output_file,
8211 " case %d: {",
8212 DECL_INSN_RESERV (decl)->insn_num);
8213 for (bypass = DECL_INSN_RESERV (decl)->bypass_list;
8214 bypass != NULL;
8215 bypass = bypass->next)
8216 {
8217 if (bypass->latency > max)
8218 max = bypass->latency;
8219 }
8220 fprintf (output_file, " return %d; }\n break;\n", max);
8221 }
8222
8223 fprintf (output_file, " }\n return default_latencies[%s];\n}\n\n",
8224 INTERNAL_INSN_CODE_NAME);
8225 }
8226
8227 /* The function outputs PHR interface function `insn_latency'. */
8228 static void
8229 output_insn_latency_func (void)
8230 {
8231 fprintf (output_file, "int\n%s (rtx %s, rtx %s)\n",
8232 INSN_LATENCY_FUNC_NAME, INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8233 fprintf (output_file, "{\n int %s, %s;\n",
8234 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME);
8235 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8236 INTERNAL_INSN_CODE_NAME, 0);
8237 output_internal_insn_code_evaluation (INSN2_PARAMETER_NAME,
8238 INTERNAL_INSN2_CODE_NAME, 0);
8239 fprintf (output_file, " return %s (%s, %s, %s, %s);\n}\n\n",
8240 INTERNAL_INSN_LATENCY_FUNC_NAME,
8241 INTERNAL_INSN_CODE_NAME, INTERNAL_INSN2_CODE_NAME,
8242 INSN_PARAMETER_NAME, INSN2_PARAMETER_NAME);
8243 }
8244
8245 /* The function outputs PHR interface function `maximal_insn_latency'. */
8246 static void
8247 output_maximal_insn_latency_func (void)
8248 {
8249 fprintf (output_file, "int\n%s (rtx %s)\n",
8250 "maximal_insn_latency", INSN_PARAMETER_NAME);
8251 fprintf (output_file, "{\n int %s;\n",
8252 INTERNAL_INSN_CODE_NAME);
8253 output_internal_insn_code_evaluation (INSN_PARAMETER_NAME,
8254 INTERNAL_INSN_CODE_NAME, 0);
8255 fprintf (output_file, " return %s (%s, %s);\n}\n\n",
8256 "internal_maximal_insn_latency",
8257 INTERNAL_INSN_CODE_NAME, INSN_PARAMETER_NAME);
8258 }
8259
8260 /* The function outputs PHR interface function `print_reservation'. */
8261 static void
8262 output_print_reservation_func (void)
8263 {
8264 decl_t decl;
8265 int i, j;
8266
8267 fprintf (output_file,
8268 "void\n%s (FILE *%s, rtx %s ATTRIBUTE_UNUSED)\n{\n",
8269 PRINT_RESERVATION_FUNC_NAME, FILE_PARAMETER_NAME,
8270 INSN_PARAMETER_NAME);
8271
8272 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8273 {
8274 fprintf (output_file, " fputs (\"%s\", %s);\n}\n\n",
8275 NOTHING_NAME, FILE_PARAMETER_NAME);
8276 return;
8277 }
8278
8279
8280 fputs (" static const char *const reservation_names[] =\n {",
8281 output_file);
8282
8283 for (i = 0, j = 0; i < description->decls_num; i++)
8284 {
8285 decl = description->decls [i];
8286 if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8287 {
8288 gcc_assert (j == DECL_INSN_RESERV (decl)->insn_num);
8289 j++;
8290
8291 fprintf (output_file, "\n \"%s\",",
8292 regexp_representation (DECL_INSN_RESERV (decl)->regexp));
8293 finish_regexp_representation ();
8294 }
8295 }
8296 gcc_assert (j == DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num);
8297
8298 fprintf (output_file, "\n \"%s\"\n };\n int %s;\n\n",
8299 NOTHING_NAME, INTERNAL_INSN_CODE_NAME);
8300
8301 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8302 INSN_PARAMETER_NAME,
8303 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8304 fprintf (output_file, " else\n\
8305 {\n\
8306 %s = %s (%s);\n\
8307 if (%s > %s)\n\
8308 %s = %s;\n\
8309 }\n",
8310 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8311 INSN_PARAMETER_NAME,
8312 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8313 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8314
8315 fprintf (output_file, " fputs (reservation_names[%s], %s);\n}\n\n",
8316 INTERNAL_INSN_CODE_NAME, FILE_PARAMETER_NAME);
8317 }
8318
8319 /* The following function is used to sort unit declaration by their
8320 names. */
8321 static int
8322 units_cmp (const void *unit1, const void *unit2)
8323 {
8324 const_unit_decl_t const u1 = *(const_unit_decl_t const*) unit1;
8325 const_unit_decl_t const u2 = *(const_unit_decl_t const*) unit2;
8326
8327 return strcmp (u1->name, u2->name);
8328 }
8329
8330 /* The following macro value is name of struct containing unit name
8331 and unit code. */
8332 #define NAME_CODE_STRUCT_NAME "name_code"
8333
8334 /* The following macro value is name of table of struct name_code. */
8335 #define NAME_CODE_TABLE_NAME "name_code_table"
8336
8337 /* The following macro values are member names for struct name_code. */
8338 #define NAME_MEMBER_NAME "name"
8339 #define CODE_MEMBER_NAME "code"
8340
8341 /* The following macro values are local variable names for function
8342 `get_cpu_unit_code'. */
8343 #define CMP_VARIABLE_NAME "cmp"
8344 #define LOW_VARIABLE_NAME "l"
8345 #define MIDDLE_VARIABLE_NAME "m"
8346 #define HIGH_VARIABLE_NAME "h"
8347
8348 /* The following function outputs function to obtain internal cpu unit
8349 code by the cpu unit name. */
8350 static void
8351 output_get_cpu_unit_code_func (void)
8352 {
8353 int i;
8354 unit_decl_t *units;
8355
8356 fprintf (output_file, "int\n%s (const char *%s)\n",
8357 GET_CPU_UNIT_CODE_FUNC_NAME, CPU_UNIT_NAME_PARAMETER_NAME);
8358 fprintf (output_file, "{\n struct %s {const char *%s; int %s;};\n",
8359 NAME_CODE_STRUCT_NAME, NAME_MEMBER_NAME, CODE_MEMBER_NAME);
8360 fprintf (output_file, " int %s, %s, %s, %s;\n", CMP_VARIABLE_NAME,
8361 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8362 fprintf (output_file, " static struct %s %s [] =\n {\n",
8363 NAME_CODE_STRUCT_NAME, NAME_CODE_TABLE_NAME);
8364 units = XNEWVEC (unit_decl_t, description->units_num);
8365 memcpy (units, units_array, sizeof (unit_decl_t) * description->units_num);
8366 qsort (units, description->units_num, sizeof (unit_decl_t), units_cmp);
8367 for (i = 0; i < description->units_num; i++)
8368 if (units [i]->query_p)
8369 fprintf (output_file, " {\"%s\", %d},\n",
8370 units[i]->name, units[i]->query_num);
8371 fprintf (output_file, " };\n\n");
8372 fprintf (output_file, " /* The following is binary search: */\n");
8373 fprintf (output_file, " %s = 0;\n", LOW_VARIABLE_NAME);
8374 fprintf (output_file, " %s = sizeof (%s) / sizeof (struct %s) - 1;\n",
8375 HIGH_VARIABLE_NAME, NAME_CODE_TABLE_NAME, NAME_CODE_STRUCT_NAME);
8376 fprintf (output_file, " while (%s <= %s)\n {\n",
8377 LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8378 fprintf (output_file, " %s = (%s + %s) / 2;\n",
8379 MIDDLE_VARIABLE_NAME, LOW_VARIABLE_NAME, HIGH_VARIABLE_NAME);
8380 fprintf (output_file, " %s = strcmp (%s, %s [%s].%s);\n",
8381 CMP_VARIABLE_NAME, CPU_UNIT_NAME_PARAMETER_NAME,
8382 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, NAME_MEMBER_NAME);
8383 fprintf (output_file, " if (%s < 0)\n", CMP_VARIABLE_NAME);
8384 fprintf (output_file, " %s = %s - 1;\n",
8385 HIGH_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8386 fprintf (output_file, " else if (%s > 0)\n", CMP_VARIABLE_NAME);
8387 fprintf (output_file, " %s = %s + 1;\n",
8388 LOW_VARIABLE_NAME, MIDDLE_VARIABLE_NAME);
8389 fprintf (output_file, " else\n");
8390 fprintf (output_file, " return %s [%s].%s;\n }\n",
8391 NAME_CODE_TABLE_NAME, MIDDLE_VARIABLE_NAME, CODE_MEMBER_NAME);
8392 fprintf (output_file, " return -1;\n}\n\n");
8393 free (units);
8394 }
8395
8396 /* The following function outputs function to check reservation of cpu
8397 unit (its internal code will be passed as the function argument) in
8398 given cpu state. */
8399 static void
8400 output_cpu_unit_reservation_p (void)
8401 {
8402 automaton_t automaton;
8403
8404 fprintf (output_file, "int\n%s (%s %s, int %s)\n",
8405 CPU_UNIT_RESERVATION_P_FUNC_NAME,
8406 STATE_TYPE_NAME, STATE_NAME,
8407 CPU_CODE_PARAMETER_NAME);
8408 fprintf (output_file, "{\n gcc_assert (%s >= 0 && %s < %d);\n",
8409 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME,
8410 description->query_units_num);
8411 if (description->query_units_num > 0)
8412 for (automaton = description->first_automaton;
8413 automaton != NULL;
8414 automaton = automaton->next_automaton)
8415 {
8416 fprintf (output_file, " if ((");
8417 output_reserved_units_table_name (output_file, automaton);
8418 fprintf (output_file, " [((struct %s *) %s)->", CHIP_NAME, STATE_NAME);
8419 output_chip_member_name (output_file, automaton);
8420 fprintf (output_file, " * %d + %s / 8] >> (%s %% 8)) & 1)\n",
8421 (description->query_units_num + 7) / 8,
8422 CPU_CODE_PARAMETER_NAME, CPU_CODE_PARAMETER_NAME);
8423 fprintf (output_file, " return 1;\n");
8424 }
8425 fprintf (output_file, " return 0;\n}\n\n");
8426 }
8427
8428 /* The following function outputs a function to check if insn
8429 has a dfa reservation. */
8430 static void
8431 output_insn_has_dfa_reservation_p (void)
8432 {
8433 fprintf (output_file,
8434 "bool\n%s (rtx %s ATTRIBUTE_UNUSED)\n{\n",
8435 INSN_HAS_DFA_RESERVATION_P_FUNC_NAME,
8436 INSN_PARAMETER_NAME);
8437
8438 if (DECL_INSN_RESERV (advance_cycle_insn_decl)->insn_num == 0)
8439 {
8440 fprintf (output_file, " return false;\n}\n\n");
8441 return;
8442 }
8443
8444 fprintf (output_file, " int %s;\n\n", INTERNAL_INSN_CODE_NAME);
8445
8446 fprintf (output_file, " if (%s == 0)\n %s = %s;\n",
8447 INSN_PARAMETER_NAME,
8448 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8449 fprintf (output_file, " else\n\
8450 {\n\
8451 %s = %s (%s);\n\
8452 if (%s > %s)\n\
8453 %s = %s;\n\
8454 }\n\n",
8455 INTERNAL_INSN_CODE_NAME, DFA_INSN_CODE_FUNC_NAME,
8456 INSN_PARAMETER_NAME,
8457 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME,
8458 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8459
8460 fprintf (output_file, " return %s != %s;\n}\n\n",
8461 INTERNAL_INSN_CODE_NAME, ADVANCE_CYCLE_VALUE_NAME);
8462 }
8463
8464 /* The function outputs PHR interface functions `dfa_clean_insn_cache'
8465 and 'dfa_clear_single_insn_cache'. */
8466 static void
8467 output_dfa_clean_insn_cache_func (void)
8468 {
8469 fprintf (output_file,
8470 "void\n%s (void)\n{\n int %s;\n\n",
8471 DFA_CLEAN_INSN_CACHE_FUNC_NAME, I_VARIABLE_NAME);
8472 fprintf (output_file,
8473 " for (%s = 0; %s < %s; %s++)\n %s [%s] = -1;\n}\n\n",
8474 I_VARIABLE_NAME, I_VARIABLE_NAME,
8475 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, I_VARIABLE_NAME,
8476 DFA_INSN_CODES_VARIABLE_NAME, I_VARIABLE_NAME);
8477
8478 fprintf (output_file,
8479 "void\n%s (rtx %s)\n{\n int %s;\n\n",
8480 DFA_CLEAR_SINGLE_INSN_CACHE_FUNC_NAME, INSN_PARAMETER_NAME,
8481 I_VARIABLE_NAME);
8482 fprintf (output_file,
8483 " %s = INSN_UID (%s);\n if (%s < %s)\n %s [%s] = -1;\n}\n\n",
8484 I_VARIABLE_NAME, INSN_PARAMETER_NAME, I_VARIABLE_NAME,
8485 DFA_INSN_CODES_LENGTH_VARIABLE_NAME, DFA_INSN_CODES_VARIABLE_NAME,
8486 I_VARIABLE_NAME);
8487 }
8488
8489 /* The function outputs PHR interface function `dfa_start'. */
8490 static void
8491 output_dfa_start_func (void)
8492 {
8493 fprintf (output_file,
8494 "void\n%s (void)\n{\n %s = get_max_uid ();\n",
8495 DFA_START_FUNC_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8496 fprintf (output_file, " %s = XNEWVEC (int, %s);\n",
8497 DFA_INSN_CODES_VARIABLE_NAME, DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
8498 fprintf (output_file, " %s ();\n}\n\n", DFA_CLEAN_INSN_CACHE_FUNC_NAME);
8499 }
8500
8501 /* The function outputs PHR interface function `dfa_finish'. */
8502 static void
8503 output_dfa_finish_func (void)
8504 {
8505 fprintf (output_file, "void\n%s (void)\n{\n free (%s);\n}\n\n",
8506 DFA_FINISH_FUNC_NAME, DFA_INSN_CODES_VARIABLE_NAME);
8507 }
8508
8509
8510
8511 /* The page contains code for output description file (readable
8512 representation of original description and generated DFA(s). */
8513
8514 /* The function outputs string representation of IR reservation. */
8515 static void
8516 output_regexp (regexp_t regexp)
8517 {
8518 fprintf (output_description_file, "%s", regexp_representation (regexp));
8519 finish_regexp_representation ();
8520 }
8521
8522 /* Output names of units in LIST separated by comma. */
8523 static void
8524 output_unit_set_el_list (unit_set_el_t list)
8525 {
8526 unit_set_el_t el;
8527
8528 for (el = list; el != NULL; el = el->next_unit_set_el)
8529 {
8530 if (el != list)
8531 fprintf (output_description_file, ", ");
8532 fprintf (output_description_file, "%s", el->unit_decl->name);
8533 }
8534 }
8535
8536 /* Output patterns in LIST separated by comma. */
8537 static void
8538 output_pattern_set_el_list (pattern_set_el_t list)
8539 {
8540 pattern_set_el_t el;
8541 int i;
8542
8543 for (el = list; el != NULL; el = el->next_pattern_set_el)
8544 {
8545 if (el != list)
8546 fprintf (output_description_file, ", ");
8547 for (i = 0; i < el->units_num; i++)
8548 fprintf (output_description_file, (i == 0 ? "%s" : " %s"),
8549 el->unit_decls [i]->name);
8550 }
8551 }
8552
8553 /* The function outputs string representation of IR define_reservation
8554 and define_insn_reservation. */
8555 static void
8556 output_description (void)
8557 {
8558 decl_t decl;
8559 int i;
8560
8561 for (i = 0; i < description->decls_num; i++)
8562 {
8563 decl = description->decls [i];
8564 if (decl->mode == dm_unit)
8565 {
8566 if (DECL_UNIT (decl)->excl_list != NULL)
8567 {
8568 fprintf (output_description_file, "unit %s exclusion_set: ",
8569 DECL_UNIT (decl)->name);
8570 output_unit_set_el_list (DECL_UNIT (decl)->excl_list);
8571 fprintf (output_description_file, "\n");
8572 }
8573 if (DECL_UNIT (decl)->presence_list != NULL)
8574 {
8575 fprintf (output_description_file, "unit %s presence_set: ",
8576 DECL_UNIT (decl)->name);
8577 output_pattern_set_el_list (DECL_UNIT (decl)->presence_list);
8578 fprintf (output_description_file, "\n");
8579 }
8580 if (DECL_UNIT (decl)->final_presence_list != NULL)
8581 {
8582 fprintf (output_description_file, "unit %s final_presence_set: ",
8583 DECL_UNIT (decl)->name);
8584 output_pattern_set_el_list
8585 (DECL_UNIT (decl)->final_presence_list);
8586 fprintf (output_description_file, "\n");
8587 }
8588 if (DECL_UNIT (decl)->absence_list != NULL)
8589 {
8590 fprintf (output_description_file, "unit %s absence_set: ",
8591 DECL_UNIT (decl)->name);
8592 output_pattern_set_el_list (DECL_UNIT (decl)->absence_list);
8593 fprintf (output_description_file, "\n");
8594 }
8595 if (DECL_UNIT (decl)->final_absence_list != NULL)
8596 {
8597 fprintf (output_description_file, "unit %s final_absence_set: ",
8598 DECL_UNIT (decl)->name);
8599 output_pattern_set_el_list
8600 (DECL_UNIT (decl)->final_absence_list);
8601 fprintf (output_description_file, "\n");
8602 }
8603 }
8604 }
8605 fprintf (output_description_file, "\n");
8606 for (i = 0; i < description->decls_num; i++)
8607 {
8608 decl = description->decls [i];
8609 if (decl->mode == dm_reserv)
8610 {
8611 fprintf (output_description_file, "reservation %s: ",
8612 DECL_RESERV (decl)->name);
8613 output_regexp (DECL_RESERV (decl)->regexp);
8614 fprintf (output_description_file, "\n");
8615 }
8616 else if (decl->mode == dm_insn_reserv && decl != advance_cycle_insn_decl)
8617 {
8618 fprintf (output_description_file, "insn reservation %s ",
8619 DECL_INSN_RESERV (decl)->name);
8620 print_rtl (output_description_file,
8621 DECL_INSN_RESERV (decl)->condexp);
8622 fprintf (output_description_file, ": ");
8623 output_regexp (DECL_INSN_RESERV (decl)->regexp);
8624 fprintf (output_description_file, "\n");
8625 }
8626 else if (decl->mode == dm_bypass)
8627 fprintf (output_description_file, "bypass %d %s %s\n",
8628 DECL_BYPASS (decl)->latency,
8629 DECL_BYPASS (decl)->out_insn_name,
8630 DECL_BYPASS (decl)->in_insn_name);
8631 }
8632 fprintf (output_description_file, "\n\f\n");
8633 }
8634
8635 /* The function outputs name of AUTOMATON. */
8636 static void
8637 output_automaton_name (FILE *f, automaton_t automaton)
8638 {
8639 if (automaton->corresponding_automaton_decl == NULL)
8640 fprintf (f, "#%d", automaton->automaton_order_num);
8641 else
8642 fprintf (f, "`%s'", automaton->corresponding_automaton_decl->name);
8643 }
8644
8645 /* Maximal length of line for pretty printing into description
8646 file. */
8647 #define MAX_LINE_LENGTH 70
8648
8649 /* The function outputs units name belonging to AUTOMATON. */
8650 static void
8651 output_automaton_units (automaton_t automaton)
8652 {
8653 decl_t decl;
8654 const char *name;
8655 int curr_line_length;
8656 int there_is_an_automaton_unit;
8657 int i;
8658
8659 fprintf (output_description_file, "\n Corresponding units:\n");
8660 fprintf (output_description_file, " ");
8661 curr_line_length = 4;
8662 there_is_an_automaton_unit = 0;
8663 for (i = 0; i < description->decls_num; i++)
8664 {
8665 decl = description->decls [i];
8666 if (decl->mode == dm_unit
8667 && (DECL_UNIT (decl)->corresponding_automaton_num
8668 == automaton->automaton_order_num))
8669 {
8670 there_is_an_automaton_unit = 1;
8671 name = DECL_UNIT (decl)->name;
8672 if (curr_line_length + strlen (name) + 1 > MAX_LINE_LENGTH )
8673 {
8674 curr_line_length = strlen (name) + 4;
8675 fprintf (output_description_file, "\n ");
8676 }
8677 else
8678 {
8679 curr_line_length += strlen (name) + 1;
8680 fprintf (output_description_file, " ");
8681 }
8682 fprintf (output_description_file, "%s", name);
8683 }
8684 }
8685 if (!there_is_an_automaton_unit)
8686 fprintf (output_description_file, "<None>");
8687 fprintf (output_description_file, "\n\n");
8688 }
8689
8690 /* The following variable is used for forming array of all possible cpu unit
8691 reservations described by the current DFA state. */
8692 static VEC(reserv_sets_t,heap) *state_reservs;
8693
8694 /* The function forms `state_reservs' for STATE. */
8695 static void
8696 add_state_reservs (state_t state)
8697 {
8698 alt_state_t curr_alt_state;
8699
8700 if (state->component_states != NULL)
8701 for (curr_alt_state = state->component_states;
8702 curr_alt_state != NULL;
8703 curr_alt_state = curr_alt_state->next_sorted_alt_state)
8704 add_state_reservs (curr_alt_state->state);
8705 else
8706 VEC_safe_push (reserv_sets_t,heap, state_reservs, state->reservs);
8707 }
8708
8709 /* The function outputs readable representation of all out arcs of
8710 STATE. */
8711 static void
8712 output_state_arcs (state_t state)
8713 {
8714 arc_t arc;
8715 ainsn_t ainsn;
8716 const char *insn_name;
8717 int curr_line_length;
8718
8719 for (arc = first_out_arc (state); arc != NULL; arc = next_out_arc (arc))
8720 {
8721 ainsn = arc->insn;
8722 gcc_assert (ainsn->first_insn_with_same_reservs);
8723 fprintf (output_description_file, " ");
8724 curr_line_length = 7;
8725 fprintf (output_description_file, "%2d: ", ainsn->insn_equiv_class_num);
8726 do
8727 {
8728 insn_name = ainsn->insn_reserv_decl->name;
8729 if (curr_line_length + strlen (insn_name) > MAX_LINE_LENGTH)
8730 {
8731 if (ainsn != arc->insn)
8732 {
8733 fprintf (output_description_file, ",\n ");
8734 curr_line_length = strlen (insn_name) + 6;
8735 }
8736 else
8737 curr_line_length += strlen (insn_name);
8738 }
8739 else
8740 {
8741 curr_line_length += strlen (insn_name);
8742 if (ainsn != arc->insn)
8743 {
8744 curr_line_length += 2;
8745 fprintf (output_description_file, ", ");
8746 }
8747 }
8748 fprintf (output_description_file, "%s", insn_name);
8749 ainsn = ainsn->next_same_reservs_insn;
8750 }
8751 while (ainsn != NULL);
8752 fprintf (output_description_file, " %d \n",
8753 arc->to_state->order_state_num);
8754 }
8755 fprintf (output_description_file, "\n");
8756 }
8757
8758 /* The following function is used for sorting possible cpu unit
8759 reservation of a DFA state. */
8760 static int
8761 state_reservs_cmp (const void *reservs_ptr_1, const void *reservs_ptr_2)
8762 {
8763 return reserv_sets_cmp (*(const_reserv_sets_t const*) reservs_ptr_1,
8764 *(const_reserv_sets_t const*) reservs_ptr_2);
8765 }
8766
8767 /* The following function is used for sorting possible cpu unit
8768 reservation of a DFA state. */
8769 static void
8770 remove_state_duplicate_reservs (void)
8771 {
8772 size_t i, j;
8773
8774 for (i = 1, j = 0; i < VEC_length (reserv_sets_t, state_reservs); i++)
8775 if (reserv_sets_cmp (VEC_index (reserv_sets_t, state_reservs, j),
8776 VEC_index (reserv_sets_t, state_reservs, i)))
8777 {
8778 j++;
8779 VEC_replace (reserv_sets_t, state_reservs, j,
8780 VEC_index (reserv_sets_t, state_reservs, i));
8781 }
8782 VEC_truncate (reserv_sets_t, state_reservs, j + 1);
8783 }
8784
8785 /* The following function output readable representation of DFA(s)
8786 state used for fast recognition of pipeline hazards. State is
8787 described by possible (current and scheduled) cpu unit
8788 reservations. */
8789 static void
8790 output_state (state_t state)
8791 {
8792 size_t i;
8793
8794 state_reservs = 0;
8795
8796 fprintf (output_description_file, " State #%d", state->order_state_num);
8797 fprintf (output_description_file,
8798 state->new_cycle_p ? " (new cycle)\n" : "\n");
8799 add_state_reservs (state);
8800 qsort (VEC_address (reserv_sets_t, state_reservs),
8801 VEC_length (reserv_sets_t, state_reservs),
8802 sizeof (reserv_sets_t), state_reservs_cmp);
8803 remove_state_duplicate_reservs ();
8804 for (i = 1; i < VEC_length (reserv_sets_t, state_reservs); i++)
8805 {
8806 fprintf (output_description_file, " ");
8807 output_reserv_sets (output_description_file,
8808 VEC_index (reserv_sets_t, state_reservs, i));
8809 fprintf (output_description_file, "\n");
8810 }
8811 fprintf (output_description_file, "\n");
8812 output_state_arcs (state);
8813 VEC_free (reserv_sets_t,heap, state_reservs);
8814 }
8815
8816 /* The following function output readable representation of
8817 DFAs used for fast recognition of pipeline hazards. */
8818 static void
8819 output_automaton_descriptions (void)
8820 {
8821 automaton_t automaton;
8822
8823 for (automaton = description->first_automaton;
8824 automaton != NULL;
8825 automaton = automaton->next_automaton)
8826 {
8827 fprintf (output_description_file, "\nAutomaton ");
8828 output_automaton_name (output_description_file, automaton);
8829 fprintf (output_description_file, "\n");
8830 output_automaton_units (automaton);
8831 pass_states (automaton, output_state);
8832 }
8833 }
8834
8835
8836
8837 /* The page contains top level function for generation DFA(s) used for
8838 PHR. */
8839
8840 /* The function outputs statistics about work of different phases of
8841 DFA generator. */
8842 static void
8843 output_statistics (FILE *f)
8844 {
8845 automaton_t automaton;
8846 int states_num;
8847 #ifndef NDEBUG
8848 int transition_comb_vect_els = 0;
8849 int transition_full_vect_els = 0;
8850 int min_issue_delay_vect_els = 0;
8851 int locked_states = 0;
8852 #endif
8853
8854 for (automaton = description->first_automaton;
8855 automaton != NULL;
8856 automaton = automaton->next_automaton)
8857 {
8858 fprintf (f, "\nAutomaton ");
8859 output_automaton_name (f, automaton);
8860 fprintf (f, "\n %5d NDFA states, %5d NDFA arcs\n",
8861 automaton->NDFA_states_num, automaton->NDFA_arcs_num);
8862 fprintf (f, " %5d DFA states, %5d DFA arcs\n",
8863 automaton->DFA_states_num, automaton->DFA_arcs_num);
8864 states_num = automaton->DFA_states_num;
8865 if (!no_minimization_flag)
8866 {
8867 fprintf (f, " %5d minimal DFA states, %5d minimal DFA arcs\n",
8868 automaton->minimal_DFA_states_num,
8869 automaton->minimal_DFA_arcs_num);
8870 states_num = automaton->minimal_DFA_states_num;
8871 }
8872 fprintf (f, " %5d all insns %5d insn equivalence classes\n",
8873 description->insns_num, automaton->insn_equiv_classes_num);
8874 fprintf (f, " %d locked states\n", automaton->locked_states);
8875 #ifndef NDEBUG
8876 fprintf
8877 (f, "%5ld transition comb vector els, %5ld trans table els: %s\n",
8878 (long) VEC_length (vect_el_t, automaton->trans_table->comb_vect),
8879 (long) VEC_length (vect_el_t, automaton->trans_table->full_vect),
8880 (comb_vect_p (automaton->trans_table)
8881 ? "use comb vect" : "use simple vect"));
8882 fprintf
8883 (f, "%5ld min delay table els, compression factor %d\n",
8884 (long) states_num * automaton->insn_equiv_classes_num,
8885 automaton->min_issue_delay_table_compression_factor);
8886 transition_comb_vect_els
8887 += VEC_length (vect_el_t, automaton->trans_table->comb_vect);
8888 transition_full_vect_els
8889 += VEC_length (vect_el_t, automaton->trans_table->full_vect);
8890 min_issue_delay_vect_els
8891 += states_num * automaton->insn_equiv_classes_num;
8892 locked_states
8893 += automaton->locked_states;
8894 #endif
8895 }
8896 #ifndef NDEBUG
8897 fprintf (f, "\n%5d all allocated states, %5d all allocated arcs\n",
8898 allocated_states_num, allocated_arcs_num);
8899 fprintf (f, "%5d all allocated alternative states\n",
8900 allocated_alt_states_num);
8901 fprintf (f, "%5d all transition comb vector els, %5d all trans table els\n",
8902 transition_comb_vect_els, transition_full_vect_els);
8903 fprintf (f, "%5d all min delay table els\n", min_issue_delay_vect_els);
8904 fprintf (f, "%5d all locked states\n", locked_states);
8905 #endif
8906 }
8907
8908 /* The function output times of work of different phases of DFA
8909 generator. */
8910 static void
8911 output_time_statistics (FILE *f)
8912 {
8913 fprintf (f, "\n transformation: ");
8914 print_active_time (f, transform_time);
8915 fprintf (f, (!ndfa_flag ? ", building DFA: " : ", building NDFA: "));
8916 print_active_time (f, NDFA_time);
8917 if (ndfa_flag)
8918 {
8919 fprintf (f, ", NDFA -> DFA: ");
8920 print_active_time (f, NDFA_to_DFA_time);
8921 }
8922 fprintf (f, "\n DFA minimization: ");
8923 print_active_time (f, minimize_time);
8924 fprintf (f, ", making insn equivalence: ");
8925 print_active_time (f, equiv_time);
8926 fprintf (f, "\n all automaton generation: ");
8927 print_active_time (f, automaton_generation_time);
8928 fprintf (f, ", output: ");
8929 print_active_time (f, output_time);
8930 fprintf (f, "\n");
8931 }
8932
8933 /* The function generates DFA (deterministic finite state automaton)
8934 for fast recognition of pipeline hazards. No errors during
8935 checking must be fixed before this function call. */
8936 static void
8937 generate (void)
8938 {
8939 automata_num = split_argument;
8940 if (description->units_num < automata_num)
8941 automata_num = description->units_num;
8942 initiate_states ();
8943 initiate_arcs ();
8944 initiate_automata_lists ();
8945 initiate_pass_states ();
8946 initiate_excl_sets ();
8947 initiate_presence_absence_pattern_sets ();
8948 automaton_generation_time = create_ticker ();
8949 create_automata ();
8950 ticker_off (&automaton_generation_time);
8951 }
8952
8953
8954
8955 /* This page mainly contains top level functions of pipeline hazards
8956 description translator. */
8957
8958 /* The following macro value is suffix of name of description file of
8959 pipeline hazards description translator. */
8960 #define STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX ".dfa"
8961
8962 /* The function returns suffix of given file name. The returned
8963 string can not be changed. */
8964 static const char *
8965 file_name_suffix (const char *file_name)
8966 {
8967 const char *last_period;
8968
8969 for (last_period = NULL; *file_name != '\0'; file_name++)
8970 if (*file_name == '.')
8971 last_period = file_name;
8972 return (last_period == NULL ? file_name : last_period);
8973 }
8974
8975 /* The function returns base name of given file name, i.e. pointer to
8976 first char after last `/' (or `\' for WIN32) in given file name,
8977 given file name itself if the directory name is absent. The
8978 returned string can not be changed. */
8979 static const char *
8980 base_file_name (const char *file_name)
8981 {
8982 int directory_name_length;
8983
8984 directory_name_length = strlen (file_name);
8985 #ifdef WIN32
8986 while (directory_name_length >= 0 && file_name[directory_name_length] != '/'
8987 && file_name[directory_name_length] != '\\')
8988 #else
8989 while (directory_name_length >= 0 && file_name[directory_name_length] != '/')
8990 #endif
8991 directory_name_length--;
8992 return file_name + directory_name_length + 1;
8993 }
8994
8995 /* The following is top level function to initialize the work of
8996 pipeline hazards description translator. */
8997 static void
8998 initiate_automaton_gen (int argc, char **argv)
8999 {
9000 const char *base_name;
9001 int i;
9002
9003 ndfa_flag = 0;
9004 split_argument = 0; /* default value */
9005 no_minimization_flag = 0;
9006 time_flag = 0;
9007 stats_flag = 0;
9008 v_flag = 0;
9009 w_flag = 0;
9010 progress_flag = 0;
9011 for (i = 2; i < argc; i++)
9012 if (strcmp (argv [i], NO_MINIMIZATION_OPTION) == 0)
9013 no_minimization_flag = 1;
9014 else if (strcmp (argv [i], TIME_OPTION) == 0)
9015 time_flag = 1;
9016 else if (strcmp (argv [i], STATS_OPTION) == 0)
9017 stats_flag = 1;
9018 else if (strcmp (argv [i], V_OPTION) == 0)
9019 v_flag = 1;
9020 else if (strcmp (argv [i], W_OPTION) == 0)
9021 w_flag = 1;
9022 else if (strcmp (argv [i], NDFA_OPTION) == 0)
9023 ndfa_flag = 1;
9024 else if (strcmp (argv [i], PROGRESS_OPTION) == 0)
9025 progress_flag = 1;
9026 else if (strcmp (argv [i], "-split") == 0)
9027 {
9028 if (i + 1 >= argc)
9029 fatal ("-split has no argument.");
9030 fatal ("option `-split' has not been implemented yet\n");
9031 /* split_argument = atoi (argument_vect [i + 1]); */
9032 }
9033
9034 /* Initialize IR storage. */
9035 obstack_init (&irp);
9036 initiate_automaton_decl_table ();
9037 initiate_insn_decl_table ();
9038 initiate_decl_table ();
9039 output_file = stdout;
9040 output_description_file = NULL;
9041 base_name = base_file_name (argv[1]);
9042 obstack_grow (&irp, base_name,
9043 strlen (base_name) - strlen (file_name_suffix (base_name)));
9044 obstack_grow (&irp, STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX,
9045 strlen (STANDARD_OUTPUT_DESCRIPTION_FILE_SUFFIX) + 1);
9046 obstack_1grow (&irp, '\0');
9047 output_description_file_name = obstack_base (&irp);
9048 obstack_finish (&irp);
9049 }
9050
9051 /* The following function checks existence at least one arc marked by
9052 each insn. */
9053 static void
9054 check_automata_insn_issues (void)
9055 {
9056 automaton_t automaton;
9057 ainsn_t ainsn, reserv_ainsn;
9058
9059 for (automaton = description->first_automaton;
9060 automaton != NULL;
9061 automaton = automaton->next_automaton)
9062 {
9063 for (ainsn = automaton->ainsn_list;
9064 ainsn != NULL;
9065 ainsn = ainsn->next_ainsn)
9066 if (ainsn->first_insn_with_same_reservs && !ainsn->arc_exists_p)
9067 {
9068 for (reserv_ainsn = ainsn;
9069 reserv_ainsn != NULL;
9070 reserv_ainsn = reserv_ainsn->next_same_reservs_insn)
9071 if (automaton->corresponding_automaton_decl != NULL)
9072 {
9073 if (!w_flag)
9074 error ("Automaton `%s': Insn `%s' will never be issued",
9075 automaton->corresponding_automaton_decl->name,
9076 reserv_ainsn->insn_reserv_decl->name);
9077 else
9078 warning
9079 (0, "Automaton `%s': Insn `%s' will never be issued",
9080 automaton->corresponding_automaton_decl->name,
9081 reserv_ainsn->insn_reserv_decl->name);
9082 }
9083 else
9084 {
9085 if (!w_flag)
9086 error ("Insn `%s' will never be issued",
9087 reserv_ainsn->insn_reserv_decl->name);
9088 else
9089 warning (0, "Insn `%s' will never be issued",
9090 reserv_ainsn->insn_reserv_decl->name);
9091 }
9092 }
9093 }
9094 }
9095
9096 /* The following vla is used for storing pointers to all achieved
9097 states. */
9098 static VEC(state_t,heap) *automaton_states;
9099
9100 /* This function is called by function pass_states to add an achieved
9101 STATE. */
9102 static void
9103 add_automaton_state (state_t state)
9104 {
9105 VEC_safe_push (state_t,heap, automaton_states, state);
9106 }
9107
9108 /* The following function forms list of important automata (whose
9109 states may be changed after the insn issue) for each insn. */
9110 static void
9111 form_important_insn_automata_lists (void)
9112 {
9113 automaton_t automaton;
9114 decl_t decl;
9115 ainsn_t ainsn;
9116 arc_t arc;
9117 int i;
9118 size_t n;
9119
9120 automaton_states = 0;
9121 /* Mark important ainsns. */
9122 for (automaton = description->first_automaton;
9123 automaton != NULL;
9124 automaton = automaton->next_automaton)
9125 {
9126 VEC_truncate (state_t, automaton_states, 0);
9127 pass_states (automaton, add_automaton_state);
9128 for (n = 0; n < VEC_length (state_t, automaton_states); n++)
9129 {
9130 state_t s = VEC_index (state_t, automaton_states, n);
9131 for (arc = first_out_arc (s);
9132 arc != NULL;
9133 arc = next_out_arc (arc))
9134 if (arc->to_state != s)
9135 {
9136 gcc_assert (arc->insn->first_insn_with_same_reservs);
9137 for (ainsn = arc->insn;
9138 ainsn != NULL;
9139 ainsn = ainsn->next_same_reservs_insn)
9140 ainsn->important_p = TRUE;
9141 }
9142 }
9143 }
9144 VEC_free (state_t,heap, automaton_states);
9145
9146 /* Create automata sets for the insns. */
9147 for (i = 0; i < description->decls_num; i++)
9148 {
9149 decl = description->decls [i];
9150 if (decl->mode == dm_insn_reserv)
9151 {
9152 automata_list_start ();
9153 for (automaton = description->first_automaton;
9154 automaton != NULL;
9155 automaton = automaton->next_automaton)
9156 for (ainsn = automaton->ainsn_list;
9157 ainsn != NULL;
9158 ainsn = ainsn->next_ainsn)
9159 if (ainsn->important_p
9160 && ainsn->insn_reserv_decl == DECL_INSN_RESERV (decl))
9161 {
9162 automata_list_add (automaton);
9163 break;
9164 }
9165 DECL_INSN_RESERV (decl)->important_automata_list
9166 = automata_list_finish ();
9167 }
9168 }
9169 }
9170
9171
9172 /* The following is top level function to generate automat(a,on) for
9173 fast recognition of pipeline hazards. */
9174 static void
9175 expand_automata (void)
9176 {
9177 int i;
9178
9179 description = XCREATENODEVAR (struct description,
9180 sizeof (struct description)
9181 /* One entry for cycle advancing insn. */
9182 + sizeof (decl_t) * VEC_length (decl_t, decls));
9183 description->decls_num = VEC_length (decl_t, decls);
9184 description->query_units_num = 0;
9185 for (i = 0; i < description->decls_num; i++)
9186 {
9187 description->decls [i] = VEC_index (decl_t, decls, i);
9188 if (description->decls [i]->mode == dm_unit
9189 && DECL_UNIT (description->decls [i])->query_p)
9190 DECL_UNIT (description->decls [i])->query_num
9191 = description->query_units_num++;
9192 }
9193 all_time = create_ticker ();
9194 check_time = create_ticker ();
9195 if (progress_flag)
9196 fprintf (stderr, "Check description...");
9197 check_all_description ();
9198 if (progress_flag)
9199 fprintf (stderr, "done\n");
9200 ticker_off (&check_time);
9201 generation_time = create_ticker ();
9202 if (!have_error)
9203 {
9204 transform_insn_regexps ();
9205 check_unit_distributions_to_automata ();
9206 }
9207 if (!have_error)
9208 {
9209 generate ();
9210 check_automata_insn_issues ();
9211 }
9212 if (!have_error)
9213 {
9214 form_important_insn_automata_lists ();
9215 }
9216 ticker_off (&generation_time);
9217 }
9218
9219 /* The following is top level function to output PHR and to finish
9220 work with pipeline description translator. */
9221 static void
9222 write_automata (void)
9223 {
9224 output_time = create_ticker ();
9225 if (progress_flag)
9226 fprintf (stderr, "Forming and outputting automata tables...");
9227 output_tables ();
9228 if (progress_flag)
9229 {
9230 fprintf (stderr, "done\n");
9231 fprintf (stderr, "Output functions to work with automata...");
9232 }
9233 output_chip_definitions ();
9234 output_max_insn_queue_index_def ();
9235 output_internal_min_issue_delay_func ();
9236 output_internal_trans_func ();
9237 /* Cache of insn dfa codes: */
9238 fprintf (output_file, "\nstatic int *%s;\n", DFA_INSN_CODES_VARIABLE_NAME);
9239 fprintf (output_file, "\nstatic int %s;\n\n",
9240 DFA_INSN_CODES_LENGTH_VARIABLE_NAME);
9241 output_dfa_insn_code_func ();
9242 output_trans_func ();
9243 output_min_issue_delay_func ();
9244 output_internal_dead_lock_func ();
9245 output_dead_lock_func ();
9246 output_size_func ();
9247 output_internal_reset_func ();
9248 output_reset_func ();
9249 output_min_insn_conflict_delay_func ();
9250 output_default_latencies ();
9251 output_internal_insn_latency_func ();
9252 output_insn_latency_func ();
9253 output_internal_maximal_insn_latency_func ();
9254 output_maximal_insn_latency_func ();
9255 output_print_reservation_func ();
9256 /* Output function get_cpu_unit_code. */
9257 fprintf (output_file, "\n#if %s\n\n", CPU_UNITS_QUERY_MACRO_NAME);
9258 output_get_cpu_unit_code_func ();
9259 output_cpu_unit_reservation_p ();
9260 output_insn_has_dfa_reservation_p ();
9261 fprintf (output_file, "\n#endif /* #if %s */\n\n",
9262 CPU_UNITS_QUERY_MACRO_NAME);
9263 output_dfa_clean_insn_cache_func ();
9264 output_dfa_start_func ();
9265 output_dfa_finish_func ();
9266 if (progress_flag)
9267 fprintf (stderr, "done\n");
9268 if (v_flag)
9269 {
9270 output_description_file = fopen (output_description_file_name, "w");
9271 if (output_description_file == NULL)
9272 {
9273 perror (output_description_file_name);
9274 exit (FATAL_EXIT_CODE);
9275 }
9276 if (progress_flag)
9277 fprintf (stderr, "Output automata description...");
9278 output_description ();
9279 output_automaton_descriptions ();
9280 if (progress_flag)
9281 fprintf (stderr, "done\n");
9282 output_statistics (output_description_file);
9283 }
9284 if (stats_flag)
9285 output_statistics (stderr);
9286 ticker_off (&output_time);
9287 if (time_flag)
9288 output_time_statistics (stderr);
9289 finish_states ();
9290 finish_arcs ();
9291 finish_automata_lists ();
9292 if (time_flag)
9293 {
9294 fprintf (stderr, "Summary:\n");
9295 fprintf (stderr, " check time ");
9296 print_active_time (stderr, check_time);
9297 fprintf (stderr, ", generation time ");
9298 print_active_time (stderr, generation_time);
9299 fprintf (stderr, ", all time ");
9300 print_active_time (stderr, all_time);
9301 fprintf (stderr, "\n");
9302 }
9303 /* Finish all work. */
9304 if (output_description_file != NULL)
9305 {
9306 fflush (output_description_file);
9307 if (ferror (stdout) != 0)
9308 fatal ("Error in writing DFA description file %s: %s",
9309 output_description_file_name, xstrerror (errno));
9310 fclose (output_description_file);
9311 }
9312 finish_automaton_decl_table ();
9313 finish_insn_decl_table ();
9314 finish_decl_table ();
9315 obstack_free (&irp, NULL);
9316 if (have_error && output_description_file != NULL)
9317 remove (output_description_file_name);
9318 }
9319
9320 int
9321 main (int argc, char **argv)
9322 {
9323 rtx desc;
9324
9325 progname = "genautomata";
9326
9327 if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
9328 return (FATAL_EXIT_CODE);
9329
9330 initiate_automaton_gen (argc, argv);
9331 while (1)
9332 {
9333 int lineno;
9334 int insn_code_number;
9335
9336 desc = read_md_rtx (&lineno, &insn_code_number);
9337 if (desc == NULL)
9338 break;
9339
9340 switch (GET_CODE (desc))
9341 {
9342 case DEFINE_CPU_UNIT:
9343 gen_cpu_unit (desc);
9344 break;
9345
9346 case DEFINE_QUERY_CPU_UNIT:
9347 gen_query_cpu_unit (desc);
9348 break;
9349
9350 case DEFINE_BYPASS:
9351 gen_bypass (desc);
9352 break;
9353
9354 case EXCLUSION_SET:
9355 gen_excl_set (desc);
9356 break;
9357
9358 case PRESENCE_SET:
9359 gen_presence_set (desc);
9360 break;
9361
9362 case FINAL_PRESENCE_SET:
9363 gen_final_presence_set (desc);
9364 break;
9365
9366 case ABSENCE_SET:
9367 gen_absence_set (desc);
9368 break;
9369
9370 case FINAL_ABSENCE_SET:
9371 gen_final_absence_set (desc);
9372 break;
9373
9374 case DEFINE_AUTOMATON:
9375 gen_automaton (desc);
9376 break;
9377
9378 case AUTOMATA_OPTION:
9379 gen_automata_option (desc);
9380 break;
9381
9382 case DEFINE_RESERVATION:
9383 gen_reserv (desc);
9384 break;
9385
9386 case DEFINE_INSN_RESERVATION:
9387 gen_insn_reserv (desc);
9388 break;
9389
9390 default:
9391 break;
9392 }
9393 }
9394
9395 if (have_error)
9396 return FATAL_EXIT_CODE;
9397
9398 puts ("/* Generated automatically by the program `genautomata'\n"
9399 " from the machine description file `md'. */\n\n"
9400 "#include \"config.h\"\n"
9401 "#include \"system.h\"\n"
9402 "#include \"coretypes.h\"\n"
9403 "#include \"tm.h\"\n"
9404 "#include \"rtl.h\"\n"
9405 "#include \"tm_p.h\"\n"
9406 "#include \"insn-config.h\"\n"
9407 "#include \"recog.h\"\n"
9408 "#include \"regs.h\"\n"
9409 "#include \"real.h\"\n"
9410 "#include \"output.h\"\n"
9411 "#include \"insn-attr.h\"\n"
9412 "#include \"toplev.h\"\n"
9413 "#include \"flags.h\"\n"
9414 "#include \"function.h\"\n");
9415
9416 if (VEC_length (decl_t, decls) > 0)
9417 {
9418 expand_automata ();
9419 write_automata ();
9420 }
9421
9422 fflush (stdout);
9423 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
9424 }