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