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