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