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