OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [genautomata.c] - Blame information for rev 404

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.