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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [genautomata.c] - Blame information for rev 816

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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