OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [genautomata.c] - Blame information for rev 867

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

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

powered by: WebSVN 2.1.0

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