1/* Generate code from machine description to compute values of attributes.
2 Copyright (C) 1991-2023 Free Software Foundation, Inc.
3 Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* This program handles insn attributes and the DEFINE_DELAY and
22 DEFINE_INSN_RESERVATION definitions.
23
24 It produces a series of functions named `get_attr_...', one for each insn
25 attribute. Each of these is given the rtx for an insn and returns a member
26 of the enum for the attribute.
27
28 These subroutines have the form of a `switch' on the INSN_CODE (via
29 `recog_memoized'). Each case either returns a constant attribute value
30 or a value that depends on tests on other attributes, the form of
31 operands, or some random C expression (encoded with a SYMBOL_REF
32 expression).
33
34 If the attribute `alternative', or a random C expression is present,
35 `constrain_operands' is called. If either of these cases of a reference to
36 an operand is found, `extract_insn' is called.
37
38 The special attribute `length' is also recognized. For this operand,
39 expressions involving the address of an operand or the current insn,
40 (address (pc)), are valid. In this case, an initial pass is made to
41 set all lengths that do not depend on address. Those that do are set to
42 the maximum length. Then each insn that depends on an address is checked
43 and possibly has its length changed. The process repeats until no further
44 changed are made. The resulting lengths are saved for use by
45 `get_attr_length'.
46
47 A special form of DEFINE_ATTR, where the expression for default value is a
48 CONST expression, indicates an attribute that is constant for a given run
49 of the compiler. The subroutine generated for these attributes has no
50 parameters as it does not depend on any particular insn. Constant
51 attributes are typically used to specify which variety of processor is
52 used.
53
54 Internal attributes are defined to handle DEFINE_DELAY and
55 DEFINE_INSN_RESERVATION. Special routines are output for these cases.
56
57 This program works by keeping a list of possible values for each attribute.
58 These include the basic attribute choices, default values for attribute, and
59 all derived quantities.
60
61 As the description file is read, the definition for each insn is saved in a
62 `struct insn_def'. When the file reading is complete, a `struct insn_ent'
63 is created for each insn and chained to the corresponding attribute value,
64 either that specified, or the default.
65
66 An optimization phase is then run. This simplifies expressions for each
67 insn. EQ_ATTR tests are resolved, whenever possible, to a test that
68 indicates when the attribute has the specified value for the insn. This
69 avoids recursive calls during compilation.
70
71 The strategy used when processing DEFINE_DELAY definitions is to create
72 arbitrarily complex expressions and have the optimization simplify them.
73
74 Once optimization is complete, any required routines and definitions
75 will be written.
76
77 An optimization that is not yet implemented is to hoist the constant
78 expressions entirely out of the routines and definitions that are written.
79 A way to do this is to iterate over all possible combinations of values
80 for constant attributes and generate a set of functions for that given
81 combination. An initialization function would be written that evaluates
82 the attributes and installs the corresponding set of routines and
83 definitions (each would be accessed through a pointer).
84
85 We use the flags in an RTX as follows:
86 `unchanging' (ATTR_IND_SIMPLIFIED_P): This rtx is fully simplified
87 independent of the insn code.
88 `in_struct' (ATTR_CURR_SIMPLIFIED_P): This rtx is fully simplified
89 for the insn code currently being processed (see optimize_attrs).
90 `return_val' (ATTR_PERMANENT_P): This rtx is permanent and unique
91 (see attr_rtx). */
92
93#define ATTR_IND_SIMPLIFIED_P(RTX) (RTX_FLAG ((RTX), unchanging))
94#define ATTR_CURR_SIMPLIFIED_P(RTX) (RTX_FLAG ((RTX), in_struct))
95#define ATTR_PERMANENT_P(RTX) (RTX_FLAG ((RTX), return_val))
96
97#if 0
98#define strcmp_check(S1, S2) ((S1) == (S2) \
99 ? 0 \
100 : (gcc_assert (strcmp ((S1), (S2))), 1))
101#else
102#define strcmp_check(S1, S2) ((S1) != (S2))
103#endif
104
105#include "bconfig.h"
106#include "system.h"
107#include "coretypes.h"
108#include "tm.h"
109#include "rtl.h"
110#include "obstack.h"
111#include "errors.h"
112#include "read-md.h"
113#include "gensupport.h"
114#include "fnmatch.h"
115
116#define DEBUG 0
117
118/* Flags for make_internal_attr's `special' parameter. */
119#define ATTR_NONE 0
120#define ATTR_SPECIAL (1 << 0)
121
122static struct obstack obstack1, obstack2;
123static struct obstack *hash_obstack = &obstack1;
124static struct obstack *temp_obstack = &obstack2;
125
126/* enough space to reserve for printing out ints */
127#define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3)
128
129/* Define structures used to record attributes and values. */
130
131/* As each DEFINE_INSN, DEFINE_PEEPHOLE, or DEFINE_ASM_ATTRIBUTES is
132 encountered, we store all the relevant information into a
133 `struct insn_def'. This is done to allow attribute definitions to occur
134 anywhere in the file. */
135
136class insn_def
137{
138public:
139 class insn_def *next; /* Next insn in chain. */
140 rtx def; /* The DEFINE_... */
141 int insn_code; /* Instruction number. */
142 int insn_index; /* Expression number in file, for errors. */
143 file_location loc; /* Where in the .md files it occurs. */
144 int num_alternatives; /* Number of alternatives. */
145 int vec_idx; /* Index of attribute vector in `def'. */
146};
147
148/* Once everything has been read in, we store in each attribute value a list
149 of insn codes that have that value. Here is the structure used for the
150 list. */
151
152struct insn_ent
153{
154 struct insn_ent *next; /* Next in chain. */
155 class insn_def *def; /* Instruction definition. */
156};
157
158/* Each value of an attribute (either constant or computed) is assigned a
159 structure which is used as the listhead of the insns that have that
160 value. */
161
162struct attr_value
163{
164 rtx value; /* Value of attribute. */
165 struct attr_value *next; /* Next attribute value in chain. */
166 struct insn_ent *first_insn; /* First insn with this value. */
167 int num_insns; /* Number of insns with this value. */
168 int has_asm_insn; /* True if this value used for `asm' insns */
169};
170
171/* Structure for each attribute. */
172
173class attr_desc
174{
175public:
176 char *name; /* Name of attribute. */
177 const char *enum_name; /* Enum name for DEFINE_ENUM_NAME. */
178 class attr_desc *next; /* Next attribute. */
179 struct attr_value *first_value; /* First value of this attribute. */
180 struct attr_value *default_val; /* Default value for this attribute. */
181 file_location loc; /* Where in the .md files it occurs. */
182 unsigned is_numeric : 1; /* Values of this attribute are numeric. */
183 unsigned is_const : 1; /* Attribute value constant for each run. */
184 unsigned is_special : 1; /* Don't call `write_attr_set'. */
185};
186
187/* Structure for each DEFINE_DELAY. */
188
189class delay_desc
190{
191public:
192 rtx def; /* DEFINE_DELAY expression. */
193 class delay_desc *next; /* Next DEFINE_DELAY. */
194 file_location loc; /* Where in the .md files it occurs. */
195 int num; /* Number of DEFINE_DELAY, starting at 1. */
196};
197
198struct attr_value_list
199{
200 struct attr_value *av;
201 struct insn_ent *ie;
202 class attr_desc *attr;
203 struct attr_value_list *next;
204};
205
206/* Listheads of above structures. */
207
208/* This one is indexed by the first character of the attribute name. */
209#define MAX_ATTRS_INDEX 256
210static class attr_desc *attrs[MAX_ATTRS_INDEX];
211static class insn_def *defs;
212static class delay_desc *delays;
213struct attr_value_list **insn_code_values;
214
215/* Other variables. */
216
217static int insn_index_number;
218static int got_define_asm_attributes;
219static int must_extract;
220static int must_constrain;
221static int address_used;
222static int length_used;
223static int num_delays;
224static int have_annul_true, have_annul_false;
225static int num_insn_ents;
226
227/* Stores, for each insn code, the number of constraint alternatives. */
228
229static int *insn_n_alternatives;
230
231/* Stores, for each insn code, a bitmap that has bits on for each possible
232 alternative. */
233
234/* Keep this in sync with recog.h. */
235typedef uint64_t alternative_mask;
236static alternative_mask *insn_alternatives;
237
238/* Used to simplify expressions. */
239
240static rtx true_rtx, false_rtx;
241
242/* Used to reduce calls to `strcmp' */
243
244static const char *alternative_name;
245static const char *length_str;
246static const char *delay_type_str;
247static const char *delay_1_0_str;
248static const char *num_delay_slots_str;
249
250/* Simplify an expression. Only call the routine if there is something to
251 simplify. */
252#define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \
253 (ATTR_IND_SIMPLIFIED_P (EXP) || ATTR_CURR_SIMPLIFIED_P (EXP) ? (EXP) \
254 : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
255
256#define DEF_ATTR_STRING(S) (attr_string ((S), strlen (S)))
257
258/* Forward declarations of functions used before their definitions, only. */
259static char *attr_string (const char *, int);
260static char *attr_printf (unsigned int, const char *, ...)
261 ATTRIBUTE_PRINTF_2;
262static rtx make_numeric_value (int);
263static class attr_desc *find_attr (const char **, int);
264static rtx mk_attr_alt (alternative_mask);
265static char *next_comma_elt (const char **);
266static rtx insert_right_side (enum rtx_code, rtx, rtx, int, int);
267static rtx copy_boolean (rtx);
268static int compares_alternatives_p (rtx);
269static void make_internal_attr (const char *, rtx, int);
270static void insert_insn_ent (struct attr_value *, struct insn_ent *);
271static void walk_attr_value (rtx);
272static int max_attr_value (rtx);
273static int min_attr_value (rtx);
274static unsigned int attr_value_alignment (rtx);
275static rtx simplify_test_exp (rtx, int, int);
276static rtx simplify_test_exp_in_temp (rtx, int, int);
277static rtx copy_rtx_unchanging (rtx);
278static bool attr_alt_subset_p (rtx, rtx);
279static bool attr_alt_subset_of_compl_p (rtx, rtx);
280static void clear_struct_flag (rtx);
281static void write_attr_valueq (FILE *, class attr_desc *, const char *);
282static struct attr_value *find_most_used (class attr_desc *);
283static void write_attr_set (FILE *, class attr_desc *, int, rtx,
284 const char *, const char *, rtx,
285 int, int, unsigned int);
286static void write_attr_case (FILE *, class attr_desc *,
287 struct attr_value *,
288 int, const char *, const char *, int, rtx);
289static void write_attr_value (FILE *, class attr_desc *, rtx);
290static void write_upcase (FILE *, const char *);
291static void write_indent (FILE *, int);
292static rtx identity_fn (rtx);
293static rtx zero_fn (rtx);
294static rtx one_fn (rtx);
295static rtx max_fn (rtx);
296static rtx min_fn (rtx);
297
298#define oballoc(T) XOBNEW (hash_obstack, T)
299#define oballocvec(T, N) XOBNEWVEC (hash_obstack, T, (N))
300
301/* This gen* file is unique, in that it writes out multiple files.
302
303 Before GCC 4.8, insn-attrtab.cc was written out containing many large
304 functions and tables. This made insn-attrtab.cc _the_ bottle-neck in
305 a parallel build, and even made it impossible to build GCC on machines
306 with relatively small RAM space (PR other/29442). Therefore, the
307 atrribute functions/tables are now written out to three separate
308 files: all "*insn_default_latency" functions go to LATENCY_FILE_NAME,
309 all "*internal_dfa_insn_code" functions go to DFA_FILE_NAME, and the
310 rest goes to ATTR_FILE_NAME. */
311
312static const char *attr_file_name = NULL;
313static const char *dfa_file_name = NULL;
314static const char *latency_file_name = NULL;
315
316static FILE *attr_file, *dfa_file, *latency_file;
317
318/* Hash table for sharing RTL and strings. */
319
320/* Each hash table slot is a bucket containing a chain of these structures.
321 Strings are given negative hash codes; RTL expressions are given positive
322 hash codes. */
323
324struct attr_hash
325{
326 struct attr_hash *next; /* Next structure in the bucket. */
327 unsigned int hashcode; /* Hash code of this rtx or string. */
328 union
329 {
330 char *str; /* The string (negative hash codes) */
331 rtx rtl; /* or the RTL recorded here. */
332 } u;
333};
334
335/* Now here is the hash table. When recording an RTL, it is added to
336 the slot whose index is the hash code mod the table size. Note
337 that the hash table is used for several kinds of RTL (see attr_rtx)
338 and for strings. While all these live in the same table, they are
339 completely independent, and the hash code is computed differently
340 for each. */
341
342#define RTL_HASH_SIZE 4093
343static struct attr_hash *attr_hash_table[RTL_HASH_SIZE];
344
345/* Here is how primitive or already-shared RTL's hash
346 codes are made. */
347#define RTL_HASH(RTL) ((intptr_t) (RTL) & 0777777)
348
349/* Add an entry to the hash table for RTL with hash code HASHCODE. */
350
351static void
352attr_hash_add_rtx (unsigned int hashcode, rtx rtl)
353{
354 struct attr_hash *h;
355
356 h = XOBNEW (hash_obstack, struct attr_hash);
357 h->hashcode = hashcode;
358 h->u.rtl = rtl;
359 h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
360 attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
361}
362
363/* Add an entry to the hash table for STRING with hash code HASHCODE. */
364
365static void
366attr_hash_add_string (unsigned int hashcode, char *str)
367{
368 struct attr_hash *h;
369
370 h = XOBNEW (hash_obstack, struct attr_hash);
371 h->hashcode = -hashcode;
372 h->u.str = str;
373 h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
374 attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
375}
376
377/* Generate an RTL expression, but avoid duplicates.
378 Set the ATTR_PERMANENT_P flag for these permanent objects.
379
380 In some cases we cannot uniquify; then we return an ordinary
381 impermanent rtx with ATTR_PERMANENT_P clear.
382
383 Args are as follows:
384
385 rtx attr_rtx (code, [element1, ..., elementn]) */
386
387static rtx
388attr_rtx_1 (enum rtx_code code, va_list p)
389{
390 rtx rt_val = NULL_RTX;/* RTX to return to caller... */
391 unsigned int hashcode;
392 struct attr_hash *h;
393 struct obstack *old_obstack = rtl_obstack;
394 int permanent_p = 1;
395
396 /* For each of several cases, search the hash table for an existing entry.
397 Use that entry if one is found; otherwise create a new RTL and add it
398 to the table. */
399
400 if (GET_RTX_CLASS (code) == RTX_UNARY)
401 {
402 rtx arg0 = va_arg (p, rtx);
403
404 if (! ATTR_PERMANENT_P (arg0))
405 permanent_p = 0;
406
407 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
408 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
409 if (h->hashcode == hashcode
410 && GET_CODE (h->u.rtl) == code
411 && XEXP (h->u.rtl, 0) == arg0)
412 return h->u.rtl;
413
414 if (h == 0)
415 {
416 rtl_obstack = hash_obstack;
417 rt_val = rtx_alloc (code);
418 XEXP (rt_val, 0) = arg0;
419 }
420 }
421 else if (GET_RTX_CLASS (code) == RTX_BIN_ARITH
422 || GET_RTX_CLASS (code) == RTX_COMM_ARITH
423 || GET_RTX_CLASS (code) == RTX_COMPARE
424 || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
425 {
426 rtx arg0 = va_arg (p, rtx);
427 rtx arg1 = va_arg (p, rtx);
428
429 if (! ATTR_PERMANENT_P (arg0) || ! ATTR_PERMANENT_P (arg1))
430 permanent_p = 0;
431
432 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
433 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
434 if (h->hashcode == hashcode
435 && GET_CODE (h->u.rtl) == code
436 && XEXP (h->u.rtl, 0) == arg0
437 && XEXP (h->u.rtl, 1) == arg1)
438 {
439 ATTR_CURR_SIMPLIFIED_P (h->u.rtl) = 0;
440 return h->u.rtl;
441 }
442
443 if (h == 0)
444 {
445 rtl_obstack = hash_obstack;
446 rt_val = rtx_alloc (code);
447 XEXP (rt_val, 0) = arg0;
448 XEXP (rt_val, 1) = arg1;
449 }
450 }
451 else if (code == SYMBOL_REF
452 || (GET_RTX_LENGTH (code) == 1
453 && GET_RTX_FORMAT (code)[0] == 's'))
454 {
455 char *arg0 = va_arg (p, char *);
456
457 arg0 = DEF_ATTR_STRING (arg0);
458
459 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0));
460 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
461 if (h->hashcode == hashcode
462 && GET_CODE (h->u.rtl) == code
463 && XSTR (h->u.rtl, 0) == arg0)
464 return h->u.rtl;
465
466 if (h == 0)
467 {
468 rtl_obstack = hash_obstack;
469 rt_val = rtx_alloc (code);
470 XSTR (rt_val, 0) = arg0;
471 if (code == SYMBOL_REF)
472 X0EXP (rt_val, 1) = NULL_RTX;
473 }
474 }
475 else if (GET_RTX_LENGTH (code) == 2
476 && GET_RTX_FORMAT (code)[0] == 's'
477 && GET_RTX_FORMAT (code)[1] == 's')
478 {
479 char *arg0 = va_arg (p, char *);
480 char *arg1 = va_arg (p, char *);
481
482 arg0 = DEF_ATTR_STRING (arg0);
483 arg1 = DEF_ATTR_STRING (arg1);
484
485 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
486 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
487 if (h->hashcode == hashcode
488 && GET_CODE (h->u.rtl) == code
489 && XSTR (h->u.rtl, 0) == arg0
490 && XSTR (h->u.rtl, 1) == arg1)
491 return h->u.rtl;
492
493 if (h == 0)
494 {
495 rtl_obstack = hash_obstack;
496 rt_val = rtx_alloc (code);
497 XSTR (rt_val, 0) = arg0;
498 XSTR (rt_val, 1) = arg1;
499 }
500 }
501 else if (GET_RTX_LENGTH (code) == 2
502 && GET_RTX_FORMAT (code)[0] == 'w'
503 && GET_RTX_FORMAT (code)[1] == 'w')
504 {
505 HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
506 HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT);
507
508 hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1));
509 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
510 if (h->hashcode == hashcode
511 && GET_CODE (h->u.rtl) == code
512 && XWINT (h->u.rtl, 0) == arg0
513 && XWINT (h->u.rtl, 1) == arg1)
514 return h->u.rtl;
515
516 if (h == 0)
517 {
518 rtl_obstack = hash_obstack;
519 rt_val = rtx_alloc (code);
520 XWINT (rt_val, 0) = arg0;
521 XWINT (rt_val, 1) = arg1;
522 }
523 }
524 else if (code == CONST_INT)
525 {
526 HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT);
527 if (arg0 == 0)
528 return false_rtx;
529 else if (arg0 == 1)
530 return true_rtx;
531 else
532 goto nohash;
533 }
534 else
535 {
536 int i; /* Array indices... */
537 const char *fmt; /* Current rtx's format... */
538 nohash:
539 rt_val = rtx_alloc (code); /* Allocate the storage space. */
540
541 fmt = GET_RTX_FORMAT (code); /* Find the right format... */
542 for (i = 0; i < GET_RTX_LENGTH (code); i++)
543 {
544 switch (*fmt++)
545 {
546 case '0': /* Unused field. */
547 break;
548
549 case 'i': /* An integer? */
550 XINT (rt_val, i) = va_arg (p, int);
551 break;
552
553 case 'w': /* A wide integer? */
554 XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT);
555 break;
556
557 case 's': /* A string? */
558 XSTR (rt_val, i) = va_arg (p, char *);
559 break;
560
561 case 'e': /* An expression? */
562 case 'u': /* An insn? Same except when printing. */
563 XEXP (rt_val, i) = va_arg (p, rtx);
564 break;
565
566 case 'E': /* An RTX vector? */
567 XVEC (rt_val, i) = va_arg (p, rtvec);
568 break;
569
570 default:
571 /* Don't need to handle 'p' for attributes. */
572 gcc_unreachable ();
573 }
574 }
575 return rt_val;
576 }
577
578 rtl_obstack = old_obstack;
579 attr_hash_add_rtx (hashcode, rtl: rt_val);
580 ATTR_PERMANENT_P (rt_val) = permanent_p;
581 return rt_val;
582}
583
584static rtx
585attr_rtx (enum rtx_code code, ...)
586{
587 rtx result;
588 va_list p;
589
590 va_start (p, code);
591 result = attr_rtx_1 (code, p);
592 va_end (p);
593 return result;
594}
595
596/* Create a new string printed with the printf line arguments into a space
597 of at most LEN bytes:
598
599 rtx attr_printf (len, format, [arg1, ..., argn]) */
600
601static char *
602attr_printf (unsigned int len, const char *fmt, ...)
603{
604 char str[256];
605 va_list p;
606
607 va_start (p, fmt);
608
609 gcc_assert (len < sizeof str); /* Leave room for \0. */
610
611 vsprintf (s: str, format: fmt, arg: p);
612 va_end (p);
613
614 return DEF_ATTR_STRING (str);
615}
616
617static rtx
618attr_eq (const char *name, const char *value)
619{
620 return attr_rtx (code: EQ_ATTR, name, value);
621}
622
623static const char *
624attr_numeral (int n)
625{
626 return XSTR (make_numeric_value (n), 0);
627}
628
629/* Return a permanent (possibly shared) copy of a string STR (not assumed
630 to be null terminated) with LEN bytes. */
631
632static char *
633attr_string (const char *str, int len)
634{
635 struct attr_hash *h;
636 unsigned int hashcode;
637 int i;
638 char *new_str;
639
640 /* Compute the hash code. */
641 hashcode = (len + 1) * 613U + (unsigned) str[0];
642 for (i = 1; i < len; i += 2)
643 hashcode = ((hashcode * 613) + (unsigned) str[i]);
644 if ((int) hashcode < 0)
645 hashcode = -hashcode;
646
647 /* Search the table for the string. */
648 for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
649 if (h->hashcode == -hashcode && h->u.str[0] == str[0]
650 && !strncmp (s1: h->u.str, s2: str, n: len))
651 return h->u.str; /* <-- return if found. */
652
653 /* Not found; create a permanent copy and add it to the hash table. */
654 new_str = XOBNEWVAR (hash_obstack, char, len + 1);
655 memcpy (dest: new_str, src: str, n: len);
656 new_str[len] = '\0';
657 attr_hash_add_string (hashcode, str: new_str);
658 rtx_reader_ptr->copy_md_ptr_loc (new_ptr: new_str, old_ptr: str);
659
660 return new_str; /* Return the new string. */
661}
662
663/* Check two rtx's for equality of contents,
664 taking advantage of the fact that if both are hashed
665 then they can't be equal unless they are the same object. */
666
667static int
668attr_equal_p (rtx x, rtx y)
669{
670 return (x == y || (! (ATTR_PERMANENT_P (x) && ATTR_PERMANENT_P (y))
671 && rtx_equal_p (x, y)));
672}
673
674/* Given a test expression EXP for attribute ATTR, ensure it is validly
675 formed. LOC is the location of the .md construct that contains EXP.
676
677 Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..))
678 and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")). Do the latter
679 test first so that (eq_attr "att" "!a1,a2,a3") works as expected.
680
681 Update the string address in EQ_ATTR expression to be the same used
682 in the attribute (or `alternative_name') to speed up subsequent
683 `find_attr' calls and eliminate most `strcmp' calls.
684
685 Return the new expression, if any. */
686
687static rtx
688check_attr_test (file_location loc, rtx exp, attr_desc *attr)
689{
690 struct attr_value *av;
691 const char *name_ptr, *p;
692 rtx orexp, newexp;
693
694 switch (GET_CODE (exp))
695 {
696 case EQ_ATTR:
697 /* Handle negation test. */
698 if (XSTR (exp, 1)[0] == '!')
699 return check_attr_test (loc,
700 exp: attr_rtx (code: NOT,
701 attr_eq (XSTR (exp, 0),
702 value: &XSTR (exp, 1)[1])),
703 attr);
704
705 else if (n_comma_elts (XSTR (exp, 1)) == 1)
706 {
707 attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
708 if (attr2 == NULL)
709 {
710 if (! strcmp (XSTR (exp, 0), s2: "alternative"))
711 return mk_attr_alt (((alternative_mask) 1)
712 << atoi (XSTR (exp, 1)));
713 else
714 fatal_at (loc, "unknown attribute `%s' in definition of"
715 " attribute `%s'", XSTR (exp, 0), attr->name);
716 }
717
718 if (attr->is_const && ! attr2->is_const)
719 fatal_at (loc, "constant attribute `%s' cannot test non-constant"
720 " attribute `%s'", attr->name, attr2->name);
721
722 /* Copy this just to make it permanent,
723 so expressions using it can be permanent too. */
724 exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));
725
726 /* It shouldn't be possible to simplify the value given to a
727 constant attribute, so don't expand this until it's time to
728 write the test expression. */
729 if (attr2->is_const)
730 ATTR_IND_SIMPLIFIED_P (exp) = 1;
731
732 if (attr2->is_numeric)
733 {
734 for (p = XSTR (exp, 1); *p; p++)
735 if (! ISDIGIT (*p))
736 fatal_at (loc, "attribute `%s' takes only numeric values",
737 attr2->name);
738 }
739 else
740 {
741 for (av = attr2->first_value; av; av = av->next)
742 if (GET_CODE (av->value) == CONST_STRING
743 && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
744 break;
745
746 if (av == NULL)
747 fatal_at (loc, "unknown value `%s' for attribute `%s'",
748 XSTR (exp, 1), attr2->name);
749 }
750 }
751 else
752 {
753 if (! strcmp (XSTR (exp, 0), s2: "alternative"))
754 {
755 int set = 0;
756
757 name_ptr = XSTR (exp, 1);
758 while ((p = next_comma_elt (&name_ptr)) != NULL)
759 set |= ((alternative_mask) 1) << atoi (nptr: p);
760
761 return mk_attr_alt (set);
762 }
763 else
764 {
765 /* Make an IOR tree of the possible values. */
766 orexp = false_rtx;
767 name_ptr = XSTR (exp, 1);
768 while ((p = next_comma_elt (&name_ptr)) != NULL)
769 {
770 newexp = attr_eq (XSTR (exp, 0), value: p);
771 orexp = insert_right_side (IOR, orexp, newexp, -2, -2);
772 }
773
774 return check_attr_test (loc, exp: orexp, attr);
775 }
776 }
777 break;
778
779 case ATTR_FLAG:
780 break;
781
782 case CONST_INT:
783 /* Either TRUE or FALSE. */
784 if (XWINT (exp, 0))
785 return true_rtx;
786 else
787 return false_rtx;
788
789 case IOR:
790 case AND:
791 XEXP (exp, 0) = check_attr_test (loc, XEXP (exp, 0), attr);
792 XEXP (exp, 1) = check_attr_test (loc, XEXP (exp, 1), attr);
793 break;
794
795 case NOT:
796 XEXP (exp, 0) = check_attr_test (loc, XEXP (exp, 0), attr);
797 break;
798
799 case MATCH_TEST:
800 exp = attr_rtx (code: MATCH_TEST, XSTR (exp, 0));
801 ATTR_IND_SIMPLIFIED_P (exp) = 1;
802 break;
803
804 case MATCH_OPERAND:
805 if (attr->is_const)
806 fatal_at (loc, "invalid operator `%s' in definition of constant"
807 " attribute `%s'", GET_RTX_NAME (GET_CODE (exp)),
808 attr->name);
809 /* These cases can't be simplified. */
810 ATTR_IND_SIMPLIFIED_P (exp) = 1;
811 break;
812
813 case LE: case LT: case GT: case GE:
814 case LEU: case LTU: case GTU: case GEU:
815 case NE: case EQ:
816 if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF
817 && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)
818 exp = attr_rtx (GET_CODE (exp),
819 attr_rtx (code: SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
820 attr_rtx (code: SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
821 /* These cases can't be simplified. */
822 ATTR_IND_SIMPLIFIED_P (exp) = 1;
823 break;
824
825 case SYMBOL_REF:
826 if (attr->is_const)
827 {
828 /* These cases are valid for constant attributes, but can't be
829 simplified. */
830 exp = attr_rtx (code: SYMBOL_REF, XSTR (exp, 0));
831 ATTR_IND_SIMPLIFIED_P (exp) = 1;
832 break;
833 }
834 /* FALLTHRU */
835 default:
836 fatal_at (loc, "invalid operator `%s' in definition of attribute"
837 " `%s'", GET_RTX_NAME (GET_CODE (exp)), attr->name);
838 }
839
840 return exp;
841}
842
843/* Given an expression EXP, ensure that it is validly formed and that
844 all named attribute values are valid for ATTR. Issue an error if not.
845 LOC is the location of the .md construct that contains EXP.
846
847 Return a perhaps modified replacement expression for the value. */
848
849static rtx
850check_attr_value (file_location loc, rtx exp, class attr_desc *attr)
851{
852 struct attr_value *av;
853 const char *p;
854 int i;
855
856 switch (GET_CODE (exp))
857 {
858 case CONST_INT:
859 if (!attr->is_numeric)
860 {
861 error_at (loc,
862 "CONST_INT not valid for non-numeric attribute `%s'",
863 attr->name);
864 break;
865 }
866
867 if (INTVAL (exp) < 0)
868 {
869 error_at (loc,
870 "negative numeric value specified for attribute `%s'",
871 attr->name);
872 break;
873 }
874 break;
875
876 case CONST_STRING:
877 if (! strcmp (XSTR (exp, 0), s2: "*"))
878 break;
879
880 if (attr->is_numeric)
881 {
882 p = XSTR (exp, 0);
883 for (; *p; p++)
884 if (! ISDIGIT (*p))
885 {
886 error_at (loc,
887 "non-numeric value specified for numeric"
888 " attribute `%s'", attr->name);
889 break;
890 }
891 break;
892 }
893
894 for (av = attr->first_value; av; av = av->next)
895 if (GET_CODE (av->value) == CONST_STRING
896 && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0)))
897 break;
898
899 if (av == NULL)
900 error_at (loc, "unknown value `%s' for attribute `%s'",
901 XSTR (exp, 0), attr->name);
902 break;
903
904 case IF_THEN_ELSE:
905 XEXP (exp, 0) = check_attr_test (loc, XEXP (exp, 0), attr);
906 XEXP (exp, 1) = check_attr_value (loc, XEXP (exp, 1), attr);
907 XEXP (exp, 2) = check_attr_value (loc, XEXP (exp, 2), attr);
908 break;
909
910 case PLUS:
911 case MINUS:
912 case MULT:
913 case DIV:
914 case MOD:
915 if (!attr->is_numeric)
916 {
917 error_at (loc, "invalid operation `%s' for non-numeric"
918 " attribute `%s'", GET_RTX_NAME (GET_CODE (exp)),
919 attr->name);
920 break;
921 }
922 /* Fall through. */
923
924 case IOR:
925 case AND:
926 XEXP (exp, 0) = check_attr_value (loc, XEXP (exp, 0), attr);
927 XEXP (exp, 1) = check_attr_value (loc, XEXP (exp, 1), attr);
928 break;
929
930 case FFS:
931 case CLZ:
932 case CTZ:
933 case POPCOUNT:
934 case PARITY:
935 case BSWAP:
936 XEXP (exp, 0) = check_attr_value (loc, XEXP (exp, 0), attr);
937 break;
938
939 case COND:
940 if (XVECLEN (exp, 0) % 2 != 0)
941 {
942 error_at (loc, "first operand of COND must have even length");
943 break;
944 }
945
946 for (i = 0; i < XVECLEN (exp, 0); i += 2)
947 {
948 XVECEXP (exp, 0, i) = check_attr_test (loc: attr->loc,
949 XVECEXP (exp, 0, i),
950 attr);
951 XVECEXP (exp, 0, i + 1)
952 = check_attr_value (loc, XVECEXP (exp, 0, i + 1), attr);
953 }
954
955 XEXP (exp, 1) = check_attr_value (loc, XEXP (exp, 1), attr);
956 break;
957
958 case ATTR:
959 {
960 class attr_desc *attr2 = find_attr (&XSTR (exp, 0), 0);
961 if (attr2 == NULL)
962 error_at (loc, "unknown attribute `%s' in ATTR",
963 XSTR (exp, 0));
964 else if (attr->is_const && ! attr2->is_const)
965 error_at (attr->loc,
966 "constant attribute `%s' cannot refer to non-constant"
967 " attribute `%s'", attr->name, attr2->name);
968 else if (attr->is_numeric != attr2->is_numeric)
969 error_at (loc,
970 "numeric attribute mismatch calling `%s' from `%s'",
971 attr2->name, attr->name);
972 }
973 break;
974
975 case SYMBOL_REF:
976 /* A constant SYMBOL_REF is valid as a constant attribute test and
977 is expanded later by make_canonical into a COND. In a non-constant
978 attribute test, it is left be. */
979 return attr_rtx (code: SYMBOL_REF, XSTR (exp, 0));
980
981 default:
982 error_at (loc, "invalid operator `%s' in definition of attribute `%s'",
983 GET_RTX_NAME (GET_CODE (exp)), attr->name);
984 break;
985 }
986
987 return exp;
988}
989
990/* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET.
991 It becomes a COND with each test being (eq_attr "alternative" "n") */
992
993static rtx
994convert_set_attr_alternative (rtx exp, class insn_def *id)
995{
996 int num_alt = id->num_alternatives;
997 rtx condexp;
998 int i;
999
1000 if (XVECLEN (exp, 1) != num_alt)
1001 {
1002 error_at (id->loc, "bad number of entries in SET_ATTR_ALTERNATIVE,"
1003 " was %d expected %d", XVECLEN (exp, 1), num_alt);
1004 return NULL_RTX;
1005 }
1006
1007 /* Make a COND with all tests but the last. Select the last value via the
1008 default. */
1009 condexp = rtx_alloc (COND);
1010 XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
1011
1012 for (i = 0; i < num_alt - 1; i++)
1013 {
1014 const char *p;
1015 p = attr_numeral (n: i);
1016
1017 XVECEXP (condexp, 0, 2 * i) = attr_eq (name: alternative_name, value: p);
1018 XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
1019 }
1020
1021 XEXP (condexp, 1) = XVECEXP (exp, 1, i);
1022
1023 return attr_rtx (code: SET, attr_rtx (code: ATTR, XSTR (exp, 0)), condexp);
1024}
1025
1026/* Given a SET_ATTR, convert to the appropriate SET. If a comma-separated
1027 list of values is given, convert to SET_ATTR_ALTERNATIVE first. */
1028
1029static rtx
1030convert_set_attr (rtx exp, class insn_def *id)
1031{
1032 rtx newexp;
1033 const char *name_ptr;
1034 char *p;
1035 int n;
1036
1037 /* See how many alternative specified. */
1038 n = n_comma_elts (XSTR (exp, 1));
1039 if (n == 1)
1040 return attr_rtx (code: SET,
1041 attr_rtx (code: ATTR, XSTR (exp, 0)),
1042 attr_rtx (code: CONST_STRING, XSTR (exp, 1)));
1043
1044 newexp = rtx_alloc (SET_ATTR_ALTERNATIVE);
1045 XSTR (newexp, 0) = XSTR (exp, 0);
1046 XVEC (newexp, 1) = rtvec_alloc (n);
1047
1048 /* Process each comma-separated name. */
1049 name_ptr = XSTR (exp, 1);
1050 n = 0;
1051 while ((p = next_comma_elt (&name_ptr)) != NULL)
1052 XVECEXP (newexp, 1, n++) = attr_rtx (code: CONST_STRING, p);
1053
1054 return convert_set_attr_alternative (exp: newexp, id);
1055}
1056
1057/* Scan all definitions, checking for validity. Also, convert any SET_ATTR
1058 and SET_ATTR_ALTERNATIVE expressions to the corresponding SET
1059 expressions. */
1060
1061static void
1062check_defs (void)
1063{
1064 class insn_def *id;
1065 class attr_desc *attr;
1066 int i;
1067 rtx value;
1068
1069 for (id = defs; id; id = id->next)
1070 {
1071 if (XVEC (id->def, id->vec_idx) == NULL)
1072 continue;
1073
1074 for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
1075 {
1076 value = XVECEXP (id->def, id->vec_idx, i);
1077 switch (GET_CODE (value))
1078 {
1079 case SET:
1080 if (GET_CODE (XEXP (value, 0)) != ATTR)
1081 {
1082 error_at (id->loc, "bad attribute set");
1083 value = NULL_RTX;
1084 }
1085 break;
1086
1087 case SET_ATTR_ALTERNATIVE:
1088 value = convert_set_attr_alternative (exp: value, id);
1089 break;
1090
1091 case SET_ATTR:
1092 value = convert_set_attr (exp: value, id);
1093 break;
1094
1095 default:
1096 error_at (id->loc, "invalid attribute code %s",
1097 GET_RTX_NAME (GET_CODE (value)));
1098 value = NULL_RTX;
1099 }
1100 if (value == NULL_RTX)
1101 continue;
1102
1103 if ((attr = find_attr (&XSTR (XEXP (value, 0), 0), 0)) == NULL)
1104 {
1105 error_at (id->loc, "unknown attribute %s",
1106 XSTR (XEXP (value, 0), 0));
1107 continue;
1108 }
1109
1110 XVECEXP (id->def, id->vec_idx, i) = value;
1111 XEXP (value, 1) = check_attr_value (loc: id->loc, XEXP (value, 1), attr);
1112 }
1113 }
1114}
1115
1116/* Given a valid expression for an attribute value, remove any IF_THEN_ELSE
1117 expressions by converting them into a COND. This removes cases from this
1118 program. Also, replace an attribute value of "*" with the default attribute
1119 value. LOC is the location to use for error reporting. */
1120
1121static rtx
1122make_canonical (file_location loc, class attr_desc *attr, rtx exp)
1123{
1124 int i;
1125 rtx newexp;
1126
1127 switch (GET_CODE (exp))
1128 {
1129 case CONST_INT:
1130 exp = make_numeric_value (INTVAL (exp));
1131 break;
1132
1133 case CONST_STRING:
1134 if (! strcmp (XSTR (exp, 0), s2: "*"))
1135 {
1136 if (attr->default_val == 0)
1137 fatal_at (loc, "(attr_value \"*\") used in invalid context");
1138 exp = attr->default_val->value;
1139 }
1140 else
1141 XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
1142
1143 break;
1144
1145 case SYMBOL_REF:
1146 if (!attr->is_const || ATTR_IND_SIMPLIFIED_P (exp))
1147 break;
1148 /* The SYMBOL_REF is constant for a given run, so mark it as unchanging.
1149 This makes the COND something that won't be considered an arbitrary
1150 expression by walk_attr_value. */
1151 ATTR_IND_SIMPLIFIED_P (exp) = 1;
1152 exp = check_attr_value (loc, exp, attr);
1153 break;
1154
1155 case IF_THEN_ELSE:
1156 newexp = rtx_alloc (COND);
1157 XVEC (newexp, 0) = rtvec_alloc (2);
1158 XVECEXP (newexp, 0, 0) = XEXP (exp, 0);
1159 XVECEXP (newexp, 0, 1) = XEXP (exp, 1);
1160
1161 XEXP (newexp, 1) = XEXP (exp, 2);
1162
1163 exp = newexp;
1164 /* Fall through to COND case since this is now a COND. */
1165 gcc_fallthrough ();
1166
1167 case COND:
1168 {
1169 int allsame = 1;
1170 rtx defval;
1171
1172 /* First, check for degenerate COND. */
1173 if (XVECLEN (exp, 0) == 0)
1174 return make_canonical (loc, attr, XEXP (exp, 1));
1175 defval = XEXP (exp, 1) = make_canonical (loc, attr, XEXP (exp, 1));
1176
1177 for (i = 0; i < XVECLEN (exp, 0); i += 2)
1178 {
1179 XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
1180 XVECEXP (exp, 0, i + 1)
1181 = make_canonical (loc, attr, XVECEXP (exp, 0, i + 1));
1182 if (! attr_equal_p (XVECEXP (exp, 0, i + 1), y: defval))
1183 allsame = 0;
1184 }
1185 if (allsame)
1186 return defval;
1187 }
1188 break;
1189
1190 default:
1191 break;
1192 }
1193
1194 return exp;
1195}
1196
1197static rtx
1198copy_boolean (rtx exp)
1199{
1200 if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
1201 return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
1202 copy_boolean (XEXP (exp, 1)));
1203 else if (GET_CODE (exp) == NOT)
1204 return attr_rtx (code: NOT, copy_boolean (XEXP (exp, 0)));
1205 if (GET_CODE (exp) == MATCH_OPERAND)
1206 {
1207 XSTR (exp, 1) = DEF_ATTR_STRING (XSTR (exp, 1));
1208 XSTR (exp, 2) = DEF_ATTR_STRING (XSTR (exp, 2));
1209 }
1210 else if (GET_CODE (exp) == EQ_ATTR)
1211 {
1212 XSTR (exp, 0) = DEF_ATTR_STRING (XSTR (exp, 0));
1213 XSTR (exp, 1) = DEF_ATTR_STRING (XSTR (exp, 1));
1214 }
1215
1216 return exp;
1217}
1218
1219/* Given a value and an attribute description, return a `struct attr_value *'
1220 that represents that value. This is either an existing structure, if the
1221 value has been previously encountered, or a newly-created structure.
1222
1223 `insn_code' is the code of an insn whose attribute has the specified
1224 value (-2 if not processing an insn). We ensure that all insns for
1225 a given value have the same number of alternatives if the value checks
1226 alternatives. LOC is the location to use for error reporting. */
1227
1228static struct attr_value *
1229get_attr_value (file_location loc, rtx value, class attr_desc *attr,
1230 int insn_code)
1231{
1232 struct attr_value *av;
1233 alternative_mask num_alt = 0;
1234
1235 value = make_canonical (loc, attr, exp: value);
1236 if (compares_alternatives_p (value))
1237 {
1238 if (insn_code < 0 || insn_alternatives == NULL)
1239 fatal_at (loc, "(eq_attr \"alternatives\" ...) used in non-insn"
1240 " context");
1241 else
1242 num_alt = insn_alternatives[insn_code];
1243 }
1244
1245 for (av = attr->first_value; av; av = av->next)
1246 if (attr_equal_p (x: value, y: av->value)
1247 && (num_alt == 0 || av->first_insn == NULL
1248 || insn_alternatives[av->first_insn->def->insn_code]))
1249 return av;
1250
1251 av = oballoc (struct attr_value);
1252 av->value = value;
1253 av->next = attr->first_value;
1254 attr->first_value = av;
1255 av->first_insn = NULL;
1256 av->num_insns = 0;
1257 av->has_asm_insn = 0;
1258
1259 return av;
1260}
1261
1262/* After all DEFINE_DELAYs have been read in, create internal attributes
1263 to generate the required routines.
1264
1265 First, we compute the number of delay slots for each insn (as a COND of
1266 each of the test expressions in DEFINE_DELAYs). Then, if more than one
1267 delay type is specified, we compute a similar function giving the
1268 DEFINE_DELAY ordinal for each insn.
1269
1270 Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that
1271 tells whether a given insn can be in that delay slot.
1272
1273 Normal attribute filling and optimization expands these to contain the
1274 information needed to handle delay slots. */
1275
1276static void
1277expand_delays (void)
1278{
1279 class delay_desc *delay;
1280 rtx condexp;
1281 rtx newexp;
1282 int i;
1283 char *p;
1284
1285 /* First, generate data for `num_delay_slots' function. */
1286
1287 condexp = rtx_alloc (COND);
1288 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1289 XEXP (condexp, 1) = make_numeric_value (0);
1290
1291 for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
1292 {
1293 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1294 XVECEXP (condexp, 0, i + 1)
1295 = make_numeric_value (XVECLEN (delay->def, 1) / 3);
1296 }
1297
1298 make_internal_attr (num_delay_slots_str, condexp, ATTR_NONE);
1299
1300 /* If more than one delay type, do the same for computing the delay type. */
1301 if (num_delays > 1)
1302 {
1303 condexp = rtx_alloc (COND);
1304 XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1305 XEXP (condexp, 1) = make_numeric_value (0);
1306
1307 for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
1308 {
1309 XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1310 XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
1311 }
1312
1313 make_internal_attr (delay_type_str, condexp, ATTR_SPECIAL);
1314 }
1315
1316 /* For each delay possibility and delay slot, compute an eligibility
1317 attribute for non-annulled insns and for each type of annulled (annul
1318 if true and annul if false). */
1319 for (delay = delays; delay; delay = delay->next)
1320 {
1321 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
1322 {
1323 condexp = XVECEXP (delay->def, 1, i);
1324 if (condexp == 0)
1325 condexp = false_rtx;
1326 newexp = attr_rtx (code: IF_THEN_ELSE, condexp,
1327 make_numeric_value (1), make_numeric_value (0));
1328
1329 p = attr_printf (len: sizeof "*delay__" + MAX_DIGITS * 2,
1330 fmt: "*delay_%d_%d", delay->num, i / 3);
1331 make_internal_attr (p, newexp, ATTR_SPECIAL);
1332
1333 if (have_annul_true)
1334 {
1335 condexp = XVECEXP (delay->def, 1, i + 1);
1336 if (condexp == 0) condexp = false_rtx;
1337 newexp = attr_rtx (code: IF_THEN_ELSE, condexp,
1338 make_numeric_value (1),
1339 make_numeric_value (0));
1340 p = attr_printf (len: sizeof "*annul_true__" + MAX_DIGITS * 2,
1341 fmt: "*annul_true_%d_%d", delay->num, i / 3);
1342 make_internal_attr (p, newexp, ATTR_SPECIAL);
1343 }
1344
1345 if (have_annul_false)
1346 {
1347 condexp = XVECEXP (delay->def, 1, i + 2);
1348 if (condexp == 0) condexp = false_rtx;
1349 newexp = attr_rtx (code: IF_THEN_ELSE, condexp,
1350 make_numeric_value (1),
1351 make_numeric_value (0));
1352 p = attr_printf (len: sizeof "*annul_false__" + MAX_DIGITS * 2,
1353 fmt: "*annul_false_%d_%d", delay->num, i / 3);
1354 make_internal_attr (p, newexp, ATTR_SPECIAL);
1355 }
1356 }
1357 }
1358}
1359
1360/* Once all attributes and insns have been read and checked, we construct for
1361 each attribute value a list of all the insns that have that value for
1362 the attribute. */
1363
1364static void
1365fill_attr (class attr_desc *attr)
1366{
1367 struct attr_value *av;
1368 struct insn_ent *ie;
1369 class insn_def *id;
1370 int i;
1371 rtx value;
1372
1373 /* Don't fill constant attributes. The value is independent of
1374 any particular insn. */
1375 if (attr->is_const)
1376 return;
1377
1378 for (id = defs; id; id = id->next)
1379 {
1380 /* If no value is specified for this insn for this attribute, use the
1381 default. */
1382 value = NULL;
1383 if (XVEC (id->def, id->vec_idx))
1384 for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
1385 if (! strcmp_check (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0),
1386 attr->name))
1387 value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
1388
1389 if (value == NULL)
1390 av = attr->default_val;
1391 else
1392 av = get_attr_value (loc: id->loc, value, attr, insn_code: id->insn_code);
1393
1394 ie = oballoc (struct insn_ent);
1395 ie->def = id;
1396 insert_insn_ent (av, ie);
1397 }
1398}
1399
1400/* Given an expression EXP, see if it is a COND or IF_THEN_ELSE that has a
1401 test that checks relative positions of insns (uses MATCH_DUP or PC).
1402 If so, replace it with what is obtained by passing the expression to
1403 ADDRESS_FN. If not but it is a COND or IF_THEN_ELSE, call this routine
1404 recursively on each value (including the default value). Otherwise,
1405 return the value returned by NO_ADDRESS_FN applied to EXP. */
1406
1407static rtx
1408substitute_address (rtx exp, rtx (*no_address_fn) (rtx),
1409 rtx (*address_fn) (rtx))
1410{
1411 int i;
1412 rtx newexp;
1413
1414 if (GET_CODE (exp) == COND)
1415 {
1416 /* See if any tests use addresses. */
1417 address_used = 0;
1418 for (i = 0; i < XVECLEN (exp, 0); i += 2)
1419 walk_attr_value (XVECEXP (exp, 0, i));
1420
1421 if (address_used)
1422 return (*address_fn) (exp);
1423
1424 /* Make a new copy of this COND, replacing each element. */
1425 newexp = rtx_alloc (COND);
1426 XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
1427 for (i = 0; i < XVECLEN (exp, 0); i += 2)
1428 {
1429 XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i);
1430 XVECEXP (newexp, 0, i + 1)
1431 = substitute_address (XVECEXP (exp, 0, i + 1),
1432 no_address_fn, address_fn);
1433 }
1434
1435 XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
1436 no_address_fn, address_fn);
1437
1438 return newexp;
1439 }
1440
1441 else if (GET_CODE (exp) == IF_THEN_ELSE)
1442 {
1443 address_used = 0;
1444 walk_attr_value (XEXP (exp, 0));
1445 if (address_used)
1446 return (*address_fn) (exp);
1447
1448 return attr_rtx (code: IF_THEN_ELSE,
1449 substitute_address (XEXP (exp, 0),
1450 no_address_fn, address_fn),
1451 substitute_address (XEXP (exp, 1),
1452 no_address_fn, address_fn),
1453 substitute_address (XEXP (exp, 2),
1454 no_address_fn, address_fn));
1455 }
1456
1457 return (*no_address_fn) (exp);
1458}
1459
1460/* Make new attributes from the `length' attribute. The following are made,
1461 each corresponding to a function called from `shorten_branches' or
1462 `get_attr_length':
1463
1464 *insn_default_length This is the length of the insn to be returned
1465 by `get_attr_length' before `shorten_branches'
1466 has been called. In each case where the length
1467 depends on relative addresses, the largest
1468 possible is used. This routine is also used
1469 to compute the initial size of the insn.
1470
1471 *insn_variable_length_p This returns 1 if the insn's length depends
1472 on relative addresses, zero otherwise.
1473
1474 *insn_current_length This is only called when it is known that the
1475 insn has a variable length and returns the
1476 current length, based on relative addresses.
1477 */
1478
1479static void
1480make_length_attrs (void)
1481{
1482 static const char *new_names[] =
1483 {
1484 "*insn_default_length",
1485 "*insn_min_length",
1486 "*insn_variable_length_p",
1487 "*insn_current_length"
1488 };
1489 static rtx (*const no_address_fn[]) (rtx)
1490 = {identity_fn,identity_fn, zero_fn, zero_fn};
1491 static rtx (*const address_fn[]) (rtx)
1492 = {max_fn, min_fn, one_fn, identity_fn};
1493 size_t i;
1494 class attr_desc *length_attr, *new_attr;
1495 struct attr_value *av, *new_av;
1496 struct insn_ent *ie, *new_ie;
1497
1498 /* See if length attribute is defined. If so, it must be numeric. Make
1499 it special so we don't output anything for it. */
1500 length_attr = find_attr (&length_str, 0);
1501 if (length_attr == 0)
1502 return;
1503
1504 if (! length_attr->is_numeric)
1505 fatal_at (length_attr->loc, "length attribute must be numeric");
1506
1507 length_attr->is_const = 0;
1508 length_attr->is_special = 1;
1509
1510 /* Make each new attribute, in turn. */
1511 for (i = 0; i < ARRAY_SIZE (new_names); i++)
1512 {
1513 make_internal_attr (new_names[i],
1514 substitute_address (exp: length_attr->default_val->value,
1515 no_address_fn: no_address_fn[i], address_fn: address_fn[i]),
1516 ATTR_NONE);
1517 new_attr = find_attr (&new_names[i], 0);
1518 for (av = length_attr->first_value; av; av = av->next)
1519 for (ie = av->first_insn; ie; ie = ie->next)
1520 {
1521 new_av = get_attr_value (loc: ie->def->loc,
1522 value: substitute_address (exp: av->value,
1523 no_address_fn: no_address_fn[i],
1524 address_fn: address_fn[i]),
1525 attr: new_attr, insn_code: ie->def->insn_code);
1526 new_ie = oballoc (struct insn_ent);
1527 new_ie->def = ie->def;
1528 insert_insn_ent (new_av, new_ie);
1529 }
1530 }
1531}
1532
1533/* Utility functions called from above routine. */
1534
1535static rtx
1536identity_fn (rtx exp)
1537{
1538 return exp;
1539}
1540
1541static rtx
1542zero_fn (rtx exp ATTRIBUTE_UNUSED)
1543{
1544 return make_numeric_value (0);
1545}
1546
1547static rtx
1548one_fn (rtx exp ATTRIBUTE_UNUSED)
1549{
1550 return make_numeric_value (1);
1551}
1552
1553static rtx
1554max_fn (rtx exp)
1555{
1556 return make_numeric_value (max_attr_value (exp));
1557}
1558
1559static rtx
1560min_fn (rtx exp)
1561{
1562 return make_numeric_value (min_attr_value (exp));
1563}
1564
1565static void
1566write_length_unit_log (FILE *outf)
1567{
1568 class attr_desc *length_attr = find_attr (&length_str, 0);
1569 struct attr_value *av;
1570 struct insn_ent *ie;
1571 unsigned int length_unit_log, length_or;
1572
1573 if (length_attr)
1574 {
1575 length_or = attr_value_alignment (length_attr->default_val->value);
1576 for (av = length_attr->first_value; av; av = av->next)
1577 for (ie = av->first_insn; ie; ie = ie->next)
1578 length_or |= attr_value_alignment (av->value);
1579
1580 length_or = ~length_or;
1581 for (length_unit_log = 0; length_or & 1; length_or >>= 1)
1582 length_unit_log++;
1583 }
1584 else
1585 length_unit_log = 0;
1586
1587 fprintf (stream: outf, format: "EXPORTED_CONST int length_unit_log = %u;\n", length_unit_log);
1588}
1589
1590/* Compute approximate cost of the expression. Used to decide whether
1591 expression is cheap enough for inline. */
1592static int
1593attr_rtx_cost (rtx x)
1594{
1595 int cost = 1;
1596 enum rtx_code code;
1597 if (!x)
1598 return 0;
1599 code = GET_CODE (x);
1600 switch (code)
1601 {
1602 case MATCH_OPERAND:
1603 if (XSTR (x, 1)[0])
1604 return 10;
1605 else
1606 return 1;
1607
1608 case EQ_ATTR_ALT:
1609 return 1;
1610
1611 case EQ_ATTR:
1612 /* Alternatives don't result into function call. */
1613 if (!strcmp_check (XSTR (x, 0), alternative_name))
1614 return 1;
1615 else
1616 return 5;
1617 default:
1618 {
1619 int i, j;
1620 const char *fmt = GET_RTX_FORMAT (code);
1621 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1622 {
1623 switch (fmt[i])
1624 {
1625 case 'V':
1626 case 'E':
1627 for (j = 0; j < XVECLEN (x, i); j++)
1628 cost += attr_rtx_cost (XVECEXP (x, i, j));
1629 break;
1630 case 'e':
1631 cost += attr_rtx_cost (XEXP (x, i));
1632 break;
1633 }
1634 }
1635 }
1636 break;
1637 }
1638 return cost;
1639}
1640
1641/* Take a COND expression and see if any of the conditions in it can be
1642 simplified. If any are known true or known false for the particular insn
1643 code, the COND can be further simplified.
1644
1645 Also call ourselves on any COND operations that are values of this COND.
1646
1647 We do not modify EXP; rather, we make and return a new rtx. */
1648
1649static rtx
1650simplify_cond (rtx exp, int insn_code, int insn_index)
1651{
1652 int i, j;
1653 /* We store the desired contents here,
1654 then build a new expression if they don't match EXP. */
1655 rtx defval = XEXP (exp, 1);
1656 rtx new_defval = XEXP (exp, 1);
1657 int len = XVECLEN (exp, 0);
1658 rtx *tests = XNEWVEC (rtx, len);
1659 int allsame = 1;
1660 rtx ret;
1661
1662 /* This lets us free all storage allocated below, if appropriate. */
1663 obstack_finish (rtl_obstack);
1664
1665 memcpy (dest: tests, XVEC (exp, 0)->elem, n: len * sizeof (rtx));
1666
1667 /* See if default value needs simplification. */
1668 if (GET_CODE (defval) == COND)
1669 new_defval = simplify_cond (exp: defval, insn_code, insn_index);
1670
1671 /* Simplify the subexpressions, and see what tests we can get rid of. */
1672
1673 for (i = 0; i < len; i += 2)
1674 {
1675 rtx newtest, newval;
1676
1677 /* Simplify this test. */
1678 newtest = simplify_test_exp_in_temp (tests[i], insn_code, insn_index);
1679 tests[i] = newtest;
1680
1681 newval = tests[i + 1];
1682 /* See if this value may need simplification. */
1683 if (GET_CODE (newval) == COND)
1684 newval = simplify_cond (exp: newval, insn_code, insn_index);
1685
1686 /* Look for ways to delete or combine this test. */
1687 if (newtest == true_rtx)
1688 {
1689 /* If test is true, make this value the default
1690 and discard this + any following tests. */
1691 len = i;
1692 defval = tests[i + 1];
1693 new_defval = newval;
1694 }
1695
1696 else if (newtest == false_rtx)
1697 {
1698 /* If test is false, discard it and its value. */
1699 for (j = i; j < len - 2; j++)
1700 tests[j] = tests[j + 2];
1701 i -= 2;
1702 len -= 2;
1703 }
1704
1705 else if (i > 0 && attr_equal_p (x: newval, y: tests[i - 1]))
1706 {
1707 /* If this value and the value for the prev test are the same,
1708 merge the tests. */
1709
1710 tests[i - 2]
1711 = insert_right_side (IOR, tests[i - 2], newtest,
1712 insn_code, insn_index);
1713
1714 /* Delete this test/value. */
1715 for (j = i; j < len - 2; j++)
1716 tests[j] = tests[j + 2];
1717 len -= 2;
1718 i -= 2;
1719 }
1720
1721 else
1722 tests[i + 1] = newval;
1723 }
1724
1725 /* If the last test in a COND has the same value
1726 as the default value, that test isn't needed. */
1727
1728 while (len > 0 && attr_equal_p (x: tests[len - 1], y: new_defval))
1729 len -= 2;
1730
1731 /* See if we changed anything. */
1732 if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
1733 allsame = 0;
1734 else
1735 for (i = 0; i < len; i++)
1736 if (! attr_equal_p (x: tests[i], XVECEXP (exp, 0, i)))
1737 {
1738 allsame = 0;
1739 break;
1740 }
1741
1742 if (len == 0)
1743 {
1744 if (GET_CODE (defval) == COND)
1745 ret = simplify_cond (exp: defval, insn_code, insn_index);
1746 else
1747 ret = defval;
1748 }
1749 else if (allsame)
1750 ret = exp;
1751 else
1752 {
1753 rtx newexp = rtx_alloc (COND);
1754
1755 XVEC (newexp, 0) = rtvec_alloc (len);
1756 memcpy (XVEC (newexp, 0)->elem, src: tests, n: len * sizeof (rtx));
1757 XEXP (newexp, 1) = new_defval;
1758 ret = newexp;
1759 }
1760 free (ptr: tests);
1761 return ret;
1762}
1763
1764/* Remove an insn entry from an attribute value. */
1765
1766static void
1767remove_insn_ent (struct attr_value *av, struct insn_ent *ie)
1768{
1769 struct insn_ent *previe;
1770
1771 if (av->first_insn == ie)
1772 av->first_insn = ie->next;
1773 else
1774 {
1775 for (previe = av->first_insn; previe->next != ie; previe = previe->next)
1776 ;
1777 previe->next = ie->next;
1778 }
1779
1780 av->num_insns--;
1781 if (ie->def->insn_code == -1)
1782 av->has_asm_insn = 0;
1783
1784 num_insn_ents--;
1785}
1786
1787/* Insert an insn entry in an attribute value list. */
1788
1789static void
1790insert_insn_ent (struct attr_value *av, struct insn_ent *ie)
1791{
1792 ie->next = av->first_insn;
1793 av->first_insn = ie;
1794 av->num_insns++;
1795 if (ie->def->insn_code == -1)
1796 av->has_asm_insn = 1;
1797
1798 num_insn_ents++;
1799}
1800
1801/* This is a utility routine to take an expression that is a tree of either
1802 AND or IOR expressions and insert a new term. The new term will be
1803 inserted at the right side of the first node whose code does not match
1804 the root. A new node will be created with the root's code. Its left
1805 side will be the old right side and its right side will be the new
1806 term.
1807
1808 If the `term' is itself a tree, all its leaves will be inserted. */
1809
1810static rtx
1811insert_right_side (enum rtx_code code, rtx exp, rtx term, int insn_code, int insn_index)
1812{
1813 rtx newexp;
1814
1815 /* Avoid consing in some special cases. */
1816 if (code == AND && term == true_rtx)
1817 return exp;
1818 if (code == AND && term == false_rtx)
1819 return false_rtx;
1820 if (code == AND && exp == true_rtx)
1821 return term;
1822 if (code == AND && exp == false_rtx)
1823 return false_rtx;
1824 if (code == IOR && term == true_rtx)
1825 return true_rtx;
1826 if (code == IOR && term == false_rtx)
1827 return exp;
1828 if (code == IOR && exp == true_rtx)
1829 return true_rtx;
1830 if (code == IOR && exp == false_rtx)
1831 return term;
1832 if (attr_equal_p (x: exp, y: term))
1833 return exp;
1834
1835 if (GET_CODE (term) == code)
1836 {
1837 exp = insert_right_side (code, exp, XEXP (term, 0),
1838 insn_code, insn_index);
1839 exp = insert_right_side (code, exp, XEXP (term, 1),
1840 insn_code, insn_index);
1841
1842 return exp;
1843 }
1844
1845 if (GET_CODE (exp) == code)
1846 {
1847 rtx new_rtx = insert_right_side (code, XEXP (exp, 1),
1848 term, insn_code, insn_index);
1849 if (new_rtx != XEXP (exp, 1))
1850 /* Make a copy of this expression and call recursively. */
1851 newexp = attr_rtx (code, XEXP (exp, 0), new_rtx);
1852 else
1853 newexp = exp;
1854 }
1855 else
1856 {
1857 /* Insert the new term. */
1858 newexp = attr_rtx (code, exp, term);
1859 }
1860
1861 return simplify_test_exp_in_temp (newexp, insn_code, insn_index);
1862}
1863
1864/* If we have an expression which AND's a bunch of
1865 (not (eq_attrq "alternative" "n"))
1866 terms, we may have covered all or all but one of the possible alternatives.
1867 If so, we can optimize. Similarly for IOR's of EQ_ATTR.
1868
1869 This routine is passed an expression and either AND or IOR. It returns a
1870 bitmask indicating which alternatives are mentioned within EXP. */
1871
1872static alternative_mask
1873compute_alternative_mask (rtx exp, enum rtx_code code)
1874{
1875 const char *string;
1876 if (GET_CODE (exp) == code)
1877 return compute_alternative_mask (XEXP (exp, 0), code)
1878 | compute_alternative_mask (XEXP (exp, 1), code);
1879
1880 else if (code == AND && GET_CODE (exp) == NOT
1881 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
1882 && XSTR (XEXP (exp, 0), 0) == alternative_name)
1883 string = XSTR (XEXP (exp, 0), 1);
1884
1885 else if (code == IOR && GET_CODE (exp) == EQ_ATTR
1886 && XSTR (exp, 0) == alternative_name)
1887 string = XSTR (exp, 1);
1888
1889 else if (GET_CODE (exp) == EQ_ATTR_ALT)
1890 {
1891 if (code == AND && XWINT (exp, 1))
1892 return XWINT (exp, 0);
1893
1894 if (code == IOR && !XWINT (exp, 1))
1895 return XWINT (exp, 0);
1896
1897 return 0;
1898 }
1899 else
1900 return 0;
1901
1902 if (string[1] == 0)
1903 return ((alternative_mask) 1) << (string[0] - '0');
1904 return ((alternative_mask) 1) << atoi (nptr: string);
1905}
1906
1907/* Given I, a single-bit mask, return RTX to compare the `alternative'
1908 attribute with the value represented by that bit. */
1909
1910static rtx
1911make_alternative_compare (alternative_mask mask)
1912{
1913 return mk_attr_alt (mask);
1914}
1915
1916/* If we are processing an (eq_attr "attr" "value") test, we find the value
1917 of "attr" for this insn code. From that value, we can compute a test
1918 showing when the EQ_ATTR will be true. This routine performs that
1919 computation. If a test condition involves an address, we leave the EQ_ATTR
1920 intact because addresses are only valid for the `length' attribute.
1921
1922 EXP is the EQ_ATTR expression and ATTR is the attribute to which
1923 it refers. VALUE is the value of that attribute for the insn
1924 corresponding to INSN_CODE and INSN_INDEX. */
1925
1926static rtx
1927evaluate_eq_attr (rtx exp, class attr_desc *attr, rtx value,
1928 int insn_code, int insn_index)
1929{
1930 rtx orexp, andexp;
1931 rtx right;
1932 rtx newexp;
1933 int i;
1934
1935 while (GET_CODE (value) == ATTR)
1936 {
1937 struct attr_value *av = NULL;
1938
1939 attr = find_attr (&XSTR (value, 0), 0);
1940
1941 if (insn_code_values)
1942 {
1943 struct attr_value_list *iv;
1944 for (iv = insn_code_values[insn_code]; iv; iv = iv->next)
1945 if (iv->attr == attr)
1946 {
1947 av = iv->av;
1948 break;
1949 }
1950 }
1951 else
1952 {
1953 struct insn_ent *ie;
1954 for (av = attr->first_value; av; av = av->next)
1955 for (ie = av->first_insn; ie; ie = ie->next)
1956 if (ie->def->insn_code == insn_code)
1957 goto got_av;
1958 }
1959 if (av)
1960 {
1961 got_av:
1962 value = av->value;
1963 }
1964 }
1965
1966 switch (GET_CODE (value))
1967 {
1968 case CONST_STRING:
1969 if (! strcmp_check (XSTR (value, 0), XSTR (exp, 1)))
1970 newexp = true_rtx;
1971 else
1972 newexp = false_rtx;
1973 break;
1974
1975 case SYMBOL_REF:
1976 {
1977 const char *prefix;
1978 char *string, *p;
1979
1980 gcc_assert (GET_CODE (exp) == EQ_ATTR);
1981 prefix = attr->enum_name ? attr->enum_name : attr->name;
1982 string = ACONCAT ((prefix, "_", XSTR (exp, 1), NULL));
1983 for (p = string; *p; p++)
1984 *p = TOUPPER (*p);
1985
1986 newexp = attr_rtx (code: EQ, value,
1987 attr_rtx (code: SYMBOL_REF,
1988 DEF_ATTR_STRING (string)));
1989 break;
1990 }
1991
1992 case COND:
1993 /* We construct an IOR of all the cases for which the
1994 requested attribute value is present. Since we start with
1995 FALSE, if it is not present, FALSE will be returned.
1996
1997 Each case is the AND of the NOT's of the previous conditions with the
1998 current condition; in the default case the current condition is TRUE.
1999
2000 For each possible COND value, call ourselves recursively.
2001
2002 The extra TRUE and FALSE expressions will be eliminated by another
2003 call to the simplification routine. */
2004
2005 orexp = false_rtx;
2006 andexp = true_rtx;
2007
2008 for (i = 0; i < XVECLEN (value, 0); i += 2)
2009 {
2010 rtx this_cond = simplify_test_exp_in_temp (XVECEXP (value, 0, i),
2011 insn_code, insn_index);
2012
2013 right = insert_right_side (code: AND, exp: andexp, term: this_cond,
2014 insn_code, insn_index);
2015 right = insert_right_side (code: AND, exp: right,
2016 term: evaluate_eq_attr (exp, attr,
2017 XVECEXP (value, 0,
2018 i + 1),
2019 insn_code, insn_index),
2020 insn_code, insn_index);
2021 orexp = insert_right_side (code: IOR, exp: orexp, term: right,
2022 insn_code, insn_index);
2023
2024 /* Add this condition into the AND expression. */
2025 newexp = attr_rtx (code: NOT, this_cond);
2026 andexp = insert_right_side (code: AND, exp: andexp, term: newexp,
2027 insn_code, insn_index);
2028 }
2029
2030 /* Handle the default case. */
2031 right = insert_right_side (code: AND, exp: andexp,
2032 term: evaluate_eq_attr (exp, attr, XEXP (value, 1),
2033 insn_code, insn_index),
2034 insn_code, insn_index);
2035 newexp = insert_right_side (code: IOR, exp: orexp, term: right, insn_code, insn_index);
2036 break;
2037
2038 default:
2039 gcc_unreachable ();
2040 }
2041
2042 /* If uses an address, must return original expression. But set the
2043 ATTR_IND_SIMPLIFIED_P bit so we don't try to simplify it again. */
2044
2045 address_used = 0;
2046 walk_attr_value (newexp);
2047
2048 if (address_used)
2049 {
2050 if (! ATTR_IND_SIMPLIFIED_P (exp))
2051 return copy_rtx_unchanging (exp);
2052 return exp;
2053 }
2054 else
2055 return newexp;
2056}
2057
2058/* This routine is called when an AND of a term with a tree of AND's is
2059 encountered. If the term or its complement is present in the tree, it
2060 can be replaced with TRUE or FALSE, respectively.
2061
2062 Note that (eq_attr "att" "v1") and (eq_attr "att" "v2") cannot both
2063 be true and hence are complementary.
2064
2065 There is one special case: If we see
2066 (and (not (eq_attr "att" "v1"))
2067 (eq_attr "att" "v2"))
2068 this can be replaced by (eq_attr "att" "v2"). To do this we need to
2069 replace the term, not anything in the AND tree. So we pass a pointer to
2070 the term. */
2071
2072static rtx
2073simplify_and_tree (rtx exp, rtx *pterm, int insn_code, int insn_index)
2074{
2075 rtx left, right;
2076 rtx newexp;
2077 rtx temp;
2078 int left_eliminates_term, right_eliminates_term;
2079
2080 if (GET_CODE (exp) == AND)
2081 {
2082 left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
2083 right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
2084 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2085 {
2086 newexp = attr_rtx (code: AND, left, right);
2087
2088 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
2089 }
2090 }
2091
2092 else if (GET_CODE (exp) == IOR)
2093 {
2094 /* For the IOR case, we do the same as above, except that we can
2095 only eliminate `term' if both sides of the IOR would do so. */
2096 temp = *pterm;
2097 left = simplify_and_tree (XEXP (exp, 0), pterm: &temp, insn_code, insn_index);
2098 left_eliminates_term = (temp == true_rtx);
2099
2100 temp = *pterm;
2101 right = simplify_and_tree (XEXP (exp, 1), pterm: &temp, insn_code, insn_index);
2102 right_eliminates_term = (temp == true_rtx);
2103
2104 if (left_eliminates_term && right_eliminates_term)
2105 *pterm = true_rtx;
2106
2107 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2108 {
2109 newexp = attr_rtx (code: IOR, left, right);
2110
2111 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
2112 }
2113 }
2114
2115 /* Check for simplifications. Do some extra checking here since this
2116 routine is called so many times. */
2117
2118 if (exp == *pterm)
2119 return true_rtx;
2120
2121 else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
2122 return false_rtx;
2123
2124 else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
2125 return false_rtx;
2126
2127 else if (GET_CODE (exp) == EQ_ATTR_ALT && GET_CODE (*pterm) == EQ_ATTR_ALT)
2128 {
2129 if (attr_alt_subset_p (*pterm, exp))
2130 return true_rtx;
2131
2132 if (attr_alt_subset_of_compl_p (*pterm, exp))
2133 return false_rtx;
2134
2135 if (attr_alt_subset_p (exp, *pterm))
2136 *pterm = true_rtx;
2137
2138 return exp;
2139 }
2140
2141 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
2142 {
2143 if (XSTR (exp, 0) != XSTR (*pterm, 0))
2144 return exp;
2145
2146 if (! strcmp_check (XSTR (exp, 1), XSTR (*pterm, 1)))
2147 return true_rtx;
2148 else
2149 return false_rtx;
2150 }
2151
2152 else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
2153 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
2154 {
2155 if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
2156 return exp;
2157
2158 if (! strcmp_check (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
2159 return false_rtx;
2160 else
2161 return true_rtx;
2162 }
2163
2164 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
2165 && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
2166 {
2167 if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
2168 return exp;
2169
2170 if (! strcmp_check (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
2171 return false_rtx;
2172 else
2173 *pterm = true_rtx;
2174 }
2175
2176 else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
2177 {
2178 if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
2179 return true_rtx;
2180 }
2181
2182 else if (GET_CODE (exp) == NOT)
2183 {
2184 if (attr_equal_p (XEXP (exp, 0), y: *pterm))
2185 return false_rtx;
2186 }
2187
2188 else if (GET_CODE (*pterm) == NOT)
2189 {
2190 if (attr_equal_p (XEXP (*pterm, 0), y: exp))
2191 return false_rtx;
2192 }
2193
2194 else if (attr_equal_p (x: exp, y: *pterm))
2195 return true_rtx;
2196
2197 return exp;
2198}
2199
2200/* Similar to `simplify_and_tree', but for IOR trees. */
2201
2202static rtx
2203simplify_or_tree (rtx exp, rtx *pterm, int insn_code, int insn_index)
2204{
2205 rtx left, right;
2206 rtx newexp;
2207 rtx temp;
2208 int left_eliminates_term, right_eliminates_term;
2209
2210 if (GET_CODE (exp) == IOR)
2211 {
2212 left = simplify_or_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
2213 right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
2214 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2215 {
2216 newexp = attr_rtx (GET_CODE (exp), left, right);
2217
2218 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
2219 }
2220 }
2221
2222 else if (GET_CODE (exp) == AND)
2223 {
2224 /* For the AND case, we do the same as above, except that we can
2225 only eliminate `term' if both sides of the AND would do so. */
2226 temp = *pterm;
2227 left = simplify_or_tree (XEXP (exp, 0), pterm: &temp, insn_code, insn_index);
2228 left_eliminates_term = (temp == false_rtx);
2229
2230 temp = *pterm;
2231 right = simplify_or_tree (XEXP (exp, 1), pterm: &temp, insn_code, insn_index);
2232 right_eliminates_term = (temp == false_rtx);
2233
2234 if (left_eliminates_term && right_eliminates_term)
2235 *pterm = false_rtx;
2236
2237 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2238 {
2239 newexp = attr_rtx (GET_CODE (exp), left, right);
2240
2241 exp = simplify_test_exp_in_temp (newexp, insn_code, insn_index);
2242 }
2243 }
2244
2245 if (attr_equal_p (x: exp, y: *pterm))
2246 return false_rtx;
2247
2248 else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), y: *pterm))
2249 return true_rtx;
2250
2251 else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), y: exp))
2252 return true_rtx;
2253
2254 else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
2255 && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
2256 && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
2257 *pterm = false_rtx;
2258
2259 else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
2260 && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
2261 && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
2262 return false_rtx;
2263
2264 return exp;
2265}
2266
2267/* Simplify test expression and use temporary obstack in order to avoid
2268 memory bloat. Use ATTR_IND_SIMPLIFIED to avoid unnecessary simplifications
2269 and avoid unnecessary copying if possible. */
2270
2271static rtx
2272simplify_test_exp_in_temp (rtx exp, int insn_code, int insn_index)
2273{
2274 rtx x;
2275 struct obstack *old;
2276 if (ATTR_IND_SIMPLIFIED_P (exp))
2277 return exp;
2278 old = rtl_obstack;
2279 rtl_obstack = temp_obstack;
2280 x = simplify_test_exp (exp, insn_code, insn_index);
2281 rtl_obstack = old;
2282 return x;
2283}
2284
2285/* Returns true if S1 is a subset of S2. */
2286
2287static bool
2288attr_alt_subset_p (rtx s1, rtx s2)
2289{
2290 switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
2291 {
2292 case (0 << 1) | 0:
2293 return !(XWINT (s1, 0) &~ XWINT (s2, 0));
2294
2295 case (0 << 1) | 1:
2296 return !(XWINT (s1, 0) & XWINT (s2, 0));
2297
2298 case (1 << 1) | 0:
2299 return false;
2300
2301 case (1 << 1) | 1:
2302 return !(XWINT (s2, 0) &~ XWINT (s1, 0));
2303
2304 default:
2305 gcc_unreachable ();
2306 }
2307}
2308
2309/* Returns true if S1 is a subset of complement of S2. */
2310
2311static bool
2312attr_alt_subset_of_compl_p (rtx s1, rtx s2)
2313{
2314 switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
2315 {
2316 case (0 << 1) | 0:
2317 return !(XWINT (s1, 0) & XWINT (s2, 0));
2318
2319 case (0 << 1) | 1:
2320 return !(XWINT (s1, 0) & ~XWINT (s2, 0));
2321
2322 case (1 << 1) | 0:
2323 return !(XWINT (s2, 0) &~ XWINT (s1, 0));
2324
2325 case (1 << 1) | 1:
2326 return false;
2327
2328 default:
2329 gcc_unreachable ();
2330 }
2331}
2332
2333/* Return EQ_ATTR_ALT expression representing intersection of S1 and S2. */
2334
2335static rtx
2336attr_alt_intersection (rtx s1, rtx s2)
2337{
2338 alternative_mask result;
2339
2340 switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
2341 {
2342 case (0 << 1) | 0:
2343 result = XWINT (s1, 0) & XWINT (s2, 0);
2344 break;
2345 case (0 << 1) | 1:
2346 result = XWINT (s1, 0) & ~XWINT (s2, 0);
2347 break;
2348 case (1 << 1) | 0:
2349 result = XWINT (s2, 0) & ~XWINT (s1, 0);
2350 break;
2351 case (1 << 1) | 1:
2352 result = XWINT (s1, 0) | XWINT (s2, 0);
2353 break;
2354 default:
2355 gcc_unreachable ();
2356 }
2357
2358 return attr_rtx (code: EQ_ATTR_ALT, result, XWINT (s1, 1) & XWINT (s2, 1));
2359}
2360
2361/* Return EQ_ATTR_ALT expression representing union of S1 and S2. */
2362
2363static rtx
2364attr_alt_union (rtx s1, rtx s2)
2365{
2366 alternative_mask result;
2367
2368 switch ((XWINT (s1, 1) << 1) | XWINT (s2, 1))
2369 {
2370 case (0 << 1) | 0:
2371 result = XWINT (s1, 0) | XWINT (s2, 0);
2372 break;
2373 case (0 << 1) | 1:
2374 result = XWINT (s2, 0) & ~XWINT (s1, 0);
2375 break;
2376 case (1 << 1) | 0:
2377 result = XWINT (s1, 0) & ~XWINT (s2, 0);
2378 break;
2379 case (1 << 1) | 1:
2380 result = XWINT (s1, 0) & XWINT (s2, 0);
2381 break;
2382 default:
2383 gcc_unreachable ();
2384 }
2385
2386 return attr_rtx (code: EQ_ATTR_ALT, result, XWINT (s1, 1) | XWINT (s2, 1));
2387}
2388
2389/* Return EQ_ATTR_ALT expression representing complement of S. */
2390
2391static rtx
2392attr_alt_complement (rtx s)
2393{
2394 return attr_rtx (code: EQ_ATTR_ALT, XWINT (s, 0),
2395 ((HOST_WIDE_INT) 1) - XWINT (s, 1));
2396}
2397
2398/* Return EQ_ATTR_ALT expression representing set containing elements set
2399 in E. */
2400
2401static rtx
2402mk_attr_alt (alternative_mask e)
2403{
2404 return attr_rtx (code: EQ_ATTR_ALT, (HOST_WIDE_INT) e, (HOST_WIDE_INT) 0);
2405}
2406
2407/* Given an expression, see if it can be simplified for a particular insn
2408 code based on the values of other attributes being tested. This can
2409 eliminate nested get_attr_... calls.
2410
2411 Note that if an endless recursion is specified in the patterns, the
2412 optimization will loop. However, it will do so in precisely the cases where
2413 an infinite recursion loop could occur during compilation. It's better that
2414 it occurs here! */
2415
2416static rtx
2417simplify_test_exp (rtx exp, int insn_code, int insn_index)
2418{
2419 rtx left, right;
2420 class attr_desc *attr;
2421 struct attr_value *av;
2422 struct insn_ent *ie;
2423 struct attr_value_list *iv;
2424 alternative_mask i;
2425 rtx newexp = exp;
2426 bool left_alt, right_alt;
2427
2428 /* Don't re-simplify something we already simplified. */
2429 if (ATTR_IND_SIMPLIFIED_P (exp) || ATTR_CURR_SIMPLIFIED_P (exp))
2430 return exp;
2431
2432 switch (GET_CODE (exp))
2433 {
2434 case AND:
2435 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
2436 if (left == false_rtx)
2437 return false_rtx;
2438 right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
2439 if (right == false_rtx)
2440 return false_rtx;
2441
2442 if (GET_CODE (left) == EQ_ATTR_ALT
2443 && GET_CODE (right) == EQ_ATTR_ALT)
2444 {
2445 exp = attr_alt_intersection (s1: left, s2: right);
2446 return simplify_test_exp (exp, insn_code, insn_index);
2447 }
2448
2449 /* If either side is an IOR and we have (eq_attr "alternative" ..")
2450 present on both sides, apply the distributive law since this will
2451 yield simplifications. */
2452 if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
2453 && compute_alternative_mask (exp: left, code: IOR)
2454 && compute_alternative_mask (exp: right, code: IOR))
2455 {
2456 if (GET_CODE (left) == IOR)
2457 std::swap (a&: left, b&: right);
2458
2459 newexp = attr_rtx (code: IOR,
2460 attr_rtx (code: AND, left, XEXP (right, 0)),
2461 attr_rtx (code: AND, left, XEXP (right, 1)));
2462
2463 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2464 }
2465
2466 /* Try with the term on both sides. */
2467 right = simplify_and_tree (exp: right, pterm: &left, insn_code, insn_index);
2468 if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
2469 left = simplify_and_tree (exp: left, pterm: &right, insn_code, insn_index);
2470
2471 if (left == false_rtx || right == false_rtx)
2472 return false_rtx;
2473 else if (left == true_rtx)
2474 {
2475 return right;
2476 }
2477 else if (right == true_rtx)
2478 {
2479 return left;
2480 }
2481 /* See if all or all but one of the insn's alternatives are specified
2482 in this tree. Optimize if so. */
2483
2484 if (GET_CODE (left) == NOT)
2485 left_alt = (GET_CODE (XEXP (left, 0)) == EQ_ATTR
2486 && XSTR (XEXP (left, 0), 0) == alternative_name);
2487 else
2488 left_alt = (GET_CODE (left) == EQ_ATTR_ALT
2489 && XWINT (left, 1));
2490
2491 if (GET_CODE (right) == NOT)
2492 right_alt = (GET_CODE (XEXP (right, 0)) == EQ_ATTR
2493 && XSTR (XEXP (right, 0), 0) == alternative_name);
2494 else
2495 right_alt = (GET_CODE (right) == EQ_ATTR_ALT
2496 && XWINT (right, 1));
2497
2498 if (insn_code >= 0
2499 && (GET_CODE (left) == AND
2500 || left_alt
2501 || GET_CODE (right) == AND
2502 || right_alt))
2503 {
2504 i = compute_alternative_mask (exp, code: AND);
2505 if (i & ~insn_alternatives[insn_code])
2506 fatal ("invalid alternative specified for pattern number %d",
2507 insn_index);
2508
2509 /* If all alternatives are excluded, this is false. */
2510 i ^= insn_alternatives[insn_code];
2511 if (i == 0)
2512 return false_rtx;
2513 else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
2514 {
2515 /* If just one excluded, AND a comparison with that one to the
2516 front of the tree. The others will be eliminated by
2517 optimization. We do not want to do this if the insn has one
2518 alternative and we have tested none of them! */
2519 left = make_alternative_compare (mask: i);
2520 right = simplify_and_tree (exp, pterm: &left, insn_code, insn_index);
2521 newexp = attr_rtx (code: AND, left, right);
2522
2523 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2524 }
2525 }
2526
2527 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2528 {
2529 newexp = attr_rtx (code: AND, left, right);
2530 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2531 }
2532 break;
2533
2534 case IOR:
2535 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
2536 if (left == true_rtx)
2537 return true_rtx;
2538 right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
2539 if (right == true_rtx)
2540 return true_rtx;
2541
2542 if (GET_CODE (left) == EQ_ATTR_ALT
2543 && GET_CODE (right) == EQ_ATTR_ALT)
2544 {
2545 exp = attr_alt_union (s1: left, s2: right);
2546 return simplify_test_exp (exp, insn_code, insn_index);
2547 }
2548
2549 right = simplify_or_tree (exp: right, pterm: &left, insn_code, insn_index);
2550 if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
2551 left = simplify_or_tree (exp: left, pterm: &right, insn_code, insn_index);
2552
2553 if (right == true_rtx || left == true_rtx)
2554 return true_rtx;
2555 else if (left == false_rtx)
2556 {
2557 return right;
2558 }
2559 else if (right == false_rtx)
2560 {
2561 return left;
2562 }
2563
2564 /* Test for simple cases where the distributive law is useful. I.e.,
2565 convert (ior (and (x) (y))
2566 (and (x) (z)))
2567 to (and (x)
2568 (ior (y) (z)))
2569 */
2570
2571 else if (GET_CODE (left) == AND && GET_CODE (right) == AND
2572 && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
2573 {
2574 newexp = attr_rtx (code: IOR, XEXP (left, 1), XEXP (right, 1));
2575
2576 left = XEXP (left, 0);
2577 right = newexp;
2578 newexp = attr_rtx (code: AND, left, right);
2579 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2580 }
2581
2582 /* Similarly,
2583 convert (ior (and (y) (x))
2584 (and (z) (x)))
2585 to (and (ior (y) (z))
2586 (x))
2587 Note that we want the common term to stay at the end.
2588 */
2589
2590 else if (GET_CODE (left) == AND && GET_CODE (right) == AND
2591 && attr_equal_p (XEXP (left, 1), XEXP (right, 1)))
2592 {
2593 newexp = attr_rtx (code: IOR, XEXP (left, 0), XEXP (right, 0));
2594
2595 left = newexp;
2596 right = XEXP (right, 1);
2597 newexp = attr_rtx (code: AND, left, right);
2598 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2599 }
2600
2601 /* See if all or all but one of the insn's alternatives are specified
2602 in this tree. Optimize if so. */
2603
2604 else if (insn_code >= 0
2605 && (GET_CODE (left) == IOR
2606 || (GET_CODE (left) == EQ_ATTR_ALT
2607 && !XWINT (left, 1))
2608 || (GET_CODE (left) == EQ_ATTR
2609 && XSTR (left, 0) == alternative_name)
2610 || GET_CODE (right) == IOR
2611 || (GET_CODE (right) == EQ_ATTR_ALT
2612 && !XWINT (right, 1))
2613 || (GET_CODE (right) == EQ_ATTR
2614 && XSTR (right, 0) == alternative_name)))
2615 {
2616 i = compute_alternative_mask (exp, code: IOR);
2617 if (i & ~insn_alternatives[insn_code])
2618 fatal ("invalid alternative specified for pattern number %d",
2619 insn_index);
2620
2621 /* If all alternatives are included, this is true. */
2622 i ^= insn_alternatives[insn_code];
2623 if (i == 0)
2624 return true_rtx;
2625 else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
2626 {
2627 /* If just one excluded, IOR a comparison with that one to the
2628 front of the tree. The others will be eliminated by
2629 optimization. We do not want to do this if the insn has one
2630 alternative and we have tested none of them! */
2631 left = make_alternative_compare (mask: i);
2632 right = simplify_and_tree (exp, pterm: &left, insn_code, insn_index);
2633 newexp = attr_rtx (code: IOR, attr_rtx (code: NOT, left), right);
2634
2635 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2636 }
2637 }
2638
2639 if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2640 {
2641 newexp = attr_rtx (code: IOR, left, right);
2642 return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2643 }
2644 break;
2645
2646 case NOT:
2647 if (GET_CODE (XEXP (exp, 0)) == NOT)
2648 {
2649 left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
2650 insn_code, insn_index);
2651 return left;
2652 }
2653
2654 left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
2655 if (GET_CODE (left) == NOT)
2656 return XEXP (left, 0);
2657
2658 if (left == false_rtx)
2659 return true_rtx;
2660 if (left == true_rtx)
2661 return false_rtx;
2662
2663 if (GET_CODE (left) == EQ_ATTR_ALT)
2664 {
2665 exp = attr_alt_complement (s: left);
2666 return simplify_test_exp (exp, insn_code, insn_index);
2667 }
2668
2669 /* Try to apply De`Morgan's laws. */
2670 if (GET_CODE (left) == IOR)
2671 {
2672 newexp = attr_rtx (code: AND,
2673 attr_rtx (code: NOT, XEXP (left, 0)),
2674 attr_rtx (code: NOT, XEXP (left, 1)));
2675
2676 newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2677 }
2678 else if (GET_CODE (left) == AND)
2679 {
2680 newexp = attr_rtx (code: IOR,
2681 attr_rtx (code: NOT, XEXP (left, 0)),
2682 attr_rtx (code: NOT, XEXP (left, 1)));
2683
2684 newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2685 }
2686 else if (left != XEXP (exp, 0))
2687 {
2688 newexp = attr_rtx (code: NOT, left);
2689 }
2690 break;
2691
2692 case EQ_ATTR_ALT:
2693 if (!XWINT (exp, 0))
2694 return XWINT (exp, 1) ? true_rtx : false_rtx;
2695 break;
2696
2697 case EQ_ATTR:
2698 if (XSTR (exp, 0) == alternative_name)
2699 {
2700 newexp = mk_attr_alt (e: ((alternative_mask) 1)
2701 << atoi (XSTR (exp, 1)));
2702 break;
2703 }
2704
2705 /* Look at the value for this insn code in the specified attribute.
2706 We normally can replace this comparison with the condition that
2707 would give this insn the values being tested for. */
2708 if (insn_code >= 0
2709 && (attr = find_attr (&XSTR (exp, 0), 0)) != NULL)
2710 {
2711 rtx x;
2712
2713 av = NULL;
2714 if (insn_code_values)
2715 {
2716 for (iv = insn_code_values[insn_code]; iv; iv = iv->next)
2717 if (iv->attr == attr)
2718 {
2719 av = iv->av;
2720 break;
2721 }
2722 }
2723 else
2724 {
2725 for (av = attr->first_value; av; av = av->next)
2726 for (ie = av->first_insn; ie; ie = ie->next)
2727 if (ie->def->insn_code == insn_code)
2728 goto got_av;
2729 }
2730
2731 if (av)
2732 {
2733 got_av:
2734 x = evaluate_eq_attr (exp, attr, value: av->value,
2735 insn_code, insn_index);
2736 x = SIMPLIFY_TEST_EXP (x, insn_code, insn_index);
2737 if (attr_rtx_cost (x) < 7)
2738 return x;
2739 }
2740 }
2741 break;
2742
2743 default:
2744 break;
2745 }
2746
2747 /* We have already simplified this expression. Simplifying it again
2748 won't buy anything unless we weren't given a valid insn code
2749 to process (i.e., we are canonicalizing something.). */
2750 if (insn_code != -2
2751 && ! ATTR_IND_SIMPLIFIED_P (newexp))
2752 return copy_rtx_unchanging (newexp);
2753
2754 return newexp;
2755}
2756
2757/* Return 1 if any EQ_ATTR subexpression of P refers to ATTR,
2758 otherwise return 0. */
2759
2760static int
2761tests_attr_p (rtx p, class attr_desc *attr)
2762{
2763 const char *fmt;
2764 int i, ie, j, je;
2765
2766 if (GET_CODE (p) == EQ_ATTR)
2767 {
2768 if (XSTR (p, 0) != attr->name)
2769 return 0;
2770 return 1;
2771 }
2772
2773 fmt = GET_RTX_FORMAT (GET_CODE (p));
2774 ie = GET_RTX_LENGTH (GET_CODE (p));
2775 for (i = 0; i < ie; i++)
2776 {
2777 switch (*fmt++)
2778 {
2779 case 'e':
2780 if (tests_attr_p (XEXP (p, i), attr))
2781 return 1;
2782 break;
2783
2784 case 'E':
2785 je = XVECLEN (p, i);
2786 for (j = 0; j < je; ++j)
2787 if (tests_attr_p (XVECEXP (p, i, j), attr))
2788 return 1;
2789 break;
2790 }
2791 }
2792
2793 return 0;
2794}
2795
2796/* Calculate a topological sorting of all attributes so that
2797 all attributes only depend on attributes in front of it.
2798 Place the result in *RET (which is a pointer to an array of
2799 attr_desc pointers), and return the size of that array. */
2800
2801static int
2802get_attr_order (class attr_desc ***ret)
2803{
2804 int i, j;
2805 int num = 0;
2806 class attr_desc *attr;
2807 class attr_desc **all, **sorted;
2808 char *handled;
2809 for (i = 0; i < MAX_ATTRS_INDEX; i++)
2810 for (attr = attrs[i]; attr; attr = attr->next)
2811 num++;
2812 all = XNEWVEC (class attr_desc *, num);
2813 sorted = XNEWVEC (class attr_desc *, num);
2814 handled = XCNEWVEC (char, num);
2815 num = 0;
2816 for (i = 0; i < MAX_ATTRS_INDEX; i++)
2817 for (attr = attrs[i]; attr; attr = attr->next)
2818 all[num++] = attr;
2819
2820 j = 0;
2821 for (i = 0; i < num; i++)
2822 if (all[i]->is_const)
2823 handled[i] = 1, sorted[j++] = all[i];
2824
2825 /* We have only few attributes hence we can live with the inner
2826 loop being O(n^2), unlike the normal fast variants of topological
2827 sorting. */
2828 while (j < num)
2829 {
2830 for (i = 0; i < num; i++)
2831 if (!handled[i])
2832 {
2833 /* Let's see if I depends on anything interesting. */
2834 int k;
2835 for (k = 0; k < num; k++)
2836 if (!handled[k])
2837 {
2838 struct attr_value *av;
2839 for (av = all[i]->first_value; av; av = av->next)
2840 if (av->num_insns != 0)
2841 if (tests_attr_p (p: av->value, attr: all[k]))
2842 break;
2843
2844 if (av)
2845 /* Something in I depends on K. */
2846 break;
2847 }
2848 if (k == num)
2849 {
2850 /* Nothing in I depended on anything intersting, so
2851 it's done. */
2852 handled[i] = 1;
2853 sorted[j++] = all[i];
2854 }
2855 }
2856 }
2857
2858 if (DEBUG)
2859 for (j = 0; j < num; j++)
2860 {
2861 class attr_desc *attr2;
2862 struct attr_value *av;
2863
2864 attr = sorted[j];
2865 fprintf (stderr, format: "%s depends on: ", attr->name);
2866 for (i = 0; i < MAX_ATTRS_INDEX; ++i)
2867 for (attr2 = attrs[i]; attr2; attr2 = attr2->next)
2868 if (!attr2->is_const)
2869 for (av = attr->first_value; av; av = av->next)
2870 if (av->num_insns != 0)
2871 if (tests_attr_p (p: av->value, attr: attr2))
2872 {
2873 fprintf (stderr, format: "%s, ", attr2->name);
2874 break;
2875 }
2876 fprintf (stderr, format: "\n");
2877 }
2878
2879 free (ptr: all);
2880 *ret = sorted;
2881 return num;
2882}
2883
2884/* Optimize the attribute lists by seeing if we can determine conditional
2885 values from the known values of other attributes. This will save subroutine
2886 calls during the compilation. NUM_INSN_CODES is the number of unique
2887 instruction codes. */
2888
2889static void
2890optimize_attrs (int num_insn_codes)
2891{
2892 class attr_desc *attr;
2893 struct attr_value *av;
2894 struct insn_ent *ie;
2895 rtx newexp;
2896 int i;
2897 struct attr_value_list *ivbuf;
2898 struct attr_value_list *iv;
2899 class attr_desc **topsort;
2900 int topnum;
2901
2902 /* For each insn code, make a list of all the insn_ent's for it,
2903 for all values for all attributes. */
2904
2905 if (num_insn_ents == 0)
2906 return;
2907
2908 /* Make 2 extra elements, for "code" values -2 and -1. */
2909 insn_code_values = XCNEWVEC (struct attr_value_list *, num_insn_codes + 2);
2910
2911 /* Offset the table address so we can index by -2 or -1. */
2912 insn_code_values += 2;
2913
2914 iv = ivbuf = XNEWVEC (struct attr_value_list, num_insn_ents);
2915
2916 /* Create the chain of insn*attr values such that we see dependend
2917 attributes after their dependencies. As we use a stack via the
2918 next pointers start from the end of the topological order. */
2919 topnum = get_attr_order (ret: &topsort);
2920 for (i = topnum - 1; i >= 0; i--)
2921 for (av = topsort[i]->first_value; av; av = av->next)
2922 for (ie = av->first_insn; ie; ie = ie->next)
2923 {
2924 iv->attr = topsort[i];
2925 iv->av = av;
2926 iv->ie = ie;
2927 iv->next = insn_code_values[ie->def->insn_code];
2928 insn_code_values[ie->def->insn_code] = iv;
2929 iv++;
2930 }
2931 free (ptr: topsort);
2932
2933 /* Sanity check on num_insn_ents. */
2934 gcc_assert (iv == ivbuf + num_insn_ents);
2935
2936 /* Process one insn code at a time. */
2937 for (i = -2; i < num_insn_codes; i++)
2938 {
2939 /* Clear the ATTR_CURR_SIMPLIFIED_P flag everywhere relevant.
2940 We use it to mean "already simplified for this insn". */
2941 for (iv = insn_code_values[i]; iv; iv = iv->next)
2942 clear_struct_flag (iv->av->value);
2943
2944 for (iv = insn_code_values[i]; iv; iv = iv->next)
2945 {
2946 struct obstack *old = rtl_obstack;
2947
2948 attr = iv->attr;
2949 av = iv->av;
2950 ie = iv->ie;
2951 if (GET_CODE (av->value) != COND)
2952 continue;
2953
2954 rtl_obstack = temp_obstack;
2955 newexp = av->value;
2956 while (GET_CODE (newexp) == COND)
2957 {
2958 rtx newexp2 = simplify_cond (exp: newexp, insn_code: ie->def->insn_code,
2959 insn_index: ie->def->insn_index);
2960 if (newexp2 == newexp)
2961 break;
2962 newexp = newexp2;
2963 }
2964
2965 rtl_obstack = old;
2966 /* If we created a new value for this instruction, and it's
2967 cheaper than the old value, and overall cheap, use that
2968 one as specific value for the current instruction.
2969 The last test is to avoid exploding the get_attr_ function
2970 sizes for no much gain. */
2971 if (newexp != av->value
2972 && attr_rtx_cost (x: newexp) < attr_rtx_cost (x: av->value)
2973 && attr_rtx_cost (x: newexp) < 26
2974 )
2975 {
2976 remove_insn_ent (av, ie);
2977 av = get_attr_value (loc: ie->def->loc, value: newexp, attr,
2978 insn_code: ie->def->insn_code);
2979 iv->av = av;
2980 insert_insn_ent (av, ie);
2981 }
2982 }
2983 }
2984
2985 free (ptr: ivbuf);
2986 free (ptr: insn_code_values - 2);
2987 insn_code_values = NULL;
2988}
2989
2990/* Clear the ATTR_CURR_SIMPLIFIED_P flag in EXP and its subexpressions. */
2991
2992static void
2993clear_struct_flag (rtx x)
2994{
2995 int i;
2996 int j;
2997 enum rtx_code code;
2998 const char *fmt;
2999
3000 ATTR_CURR_SIMPLIFIED_P (x) = 0;
3001 if (ATTR_IND_SIMPLIFIED_P (x))
3002 return;
3003
3004 code = GET_CODE (x);
3005
3006 switch (code)
3007 {
3008 case REG:
3009 CASE_CONST_ANY:
3010 case MATCH_TEST:
3011 case SYMBOL_REF:
3012 case CODE_LABEL:
3013 case PC:
3014 case EQ_ATTR:
3015 case ATTR_FLAG:
3016 return;
3017
3018 default:
3019 break;
3020 }
3021
3022 /* Compare the elements. If any pair of corresponding elements
3023 fail to match, return 0 for the whole things. */
3024
3025 fmt = GET_RTX_FORMAT (code);
3026 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3027 {
3028 switch (fmt[i])
3029 {
3030 case 'V':
3031 case 'E':
3032 for (j = 0; j < XVECLEN (x, i); j++)
3033 clear_struct_flag (XVECEXP (x, i, j));
3034 break;
3035
3036 case 'e':
3037 clear_struct_flag (XEXP (x, i));
3038 break;
3039 }
3040 }
3041}
3042
3043/* Add attribute value NAME to the beginning of ATTR's list. */
3044
3045static void
3046add_attr_value (class attr_desc *attr, const char *name)
3047{
3048 struct attr_value *av;
3049
3050 av = oballoc (struct attr_value);
3051 av->value = attr_rtx (code: CONST_STRING, name);
3052 av->next = attr->first_value;
3053 attr->first_value = av;
3054 av->first_insn = NULL;
3055 av->num_insns = 0;
3056 av->has_asm_insn = 0;
3057}
3058
3059/* Create table entries for DEFINE_ATTR or DEFINE_ENUM_ATTR. */
3060
3061static void
3062gen_attr (md_rtx_info *info)
3063{
3064 struct enum_type *et;
3065 struct enum_value *ev;
3066 class attr_desc *attr;
3067 const char *name_ptr;
3068 char *p;
3069 rtx def = info->def;
3070
3071 /* Make a new attribute structure. Check for duplicate by looking at
3072 attr->default_val, since it is initialized by this routine. */
3073 attr = find_attr (&XSTR (def, 0), 1);
3074 if (attr->default_val)
3075 {
3076 error_at (info->loc, "duplicate definition for attribute %s",
3077 attr->name);
3078 message_at (attr->loc, "previous definition");
3079 return;
3080 }
3081 attr->loc = info->loc;
3082
3083 if (GET_CODE (def) == DEFINE_ENUM_ATTR)
3084 {
3085 attr->enum_name = XSTR (def, 1);
3086 et = rtx_reader_ptr->lookup_enum_type (XSTR (def, 1));
3087 if (!et || !et->md_p)
3088 error_at (info->loc, "No define_enum called `%s' defined",
3089 attr->name);
3090 if (et)
3091 for (ev = et->values; ev; ev = ev->next)
3092 add_attr_value (attr, name: ev->name);
3093 }
3094 else if (*XSTR (def, 1) == '\0')
3095 attr->is_numeric = 1;
3096 else
3097 {
3098 name_ptr = XSTR (def, 1);
3099 while ((p = next_comma_elt (&name_ptr)) != NULL)
3100 add_attr_value (attr, name: p);
3101 }
3102
3103 if (GET_CODE (XEXP (def, 2)) == CONST)
3104 {
3105 attr->is_const = 1;
3106 if (attr->is_numeric)
3107 error_at (info->loc,
3108 "constant attributes may not take numeric values");
3109
3110 /* Get rid of the CONST node. It is allowed only at top-level. */
3111 XEXP (def, 2) = XEXP (XEXP (def, 2), 0);
3112 }
3113
3114 if (! strcmp_check (attr->name, length_str) && ! attr->is_numeric)
3115 error_at (info->loc, "`length' attribute must take numeric values");
3116
3117 /* Set up the default value. */
3118 XEXP (def, 2) = check_attr_value (loc: info->loc, XEXP (def, 2), attr);
3119 attr->default_val = get_attr_value (loc: info->loc, XEXP (def, 2), attr, insn_code: -2);
3120}
3121
3122/* Given a pattern for DEFINE_PEEPHOLE or DEFINE_INSN, return the number of
3123 alternatives in the constraints. Assume all MATCH_OPERANDs have the same
3124 number of alternatives as this should be checked elsewhere. */
3125
3126static int
3127count_alternatives (rtx exp)
3128{
3129 int i, j, n;
3130 const char *fmt;
3131
3132 if (GET_CODE (exp) == MATCH_OPERAND)
3133 return n_comma_elts (XSTR (exp, 2));
3134
3135 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
3136 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
3137 switch (*fmt++)
3138 {
3139 case 'e':
3140 case 'u':
3141 n = count_alternatives (XEXP (exp, i));
3142 if (n)
3143 return n;
3144 break;
3145
3146 case 'E':
3147 case 'V':
3148 if (XVEC (exp, i) != NULL)
3149 for (j = 0; j < XVECLEN (exp, i); j++)
3150 {
3151 n = count_alternatives (XVECEXP (exp, i, j));
3152 if (n)
3153 return n;
3154 }
3155 }
3156
3157 return 0;
3158}
3159
3160/* Returns nonzero if the given expression contains an EQ_ATTR with the
3161 `alternative' attribute. */
3162
3163static int
3164compares_alternatives_p (rtx exp)
3165{
3166 int i, j;
3167 const char *fmt;
3168
3169 if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name)
3170 return 1;
3171
3172 for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
3173 i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
3174 switch (*fmt++)
3175 {
3176 case 'e':
3177 case 'u':
3178 if (compares_alternatives_p (XEXP (exp, i)))
3179 return 1;
3180 break;
3181
3182 case 'E':
3183 for (j = 0; j < XVECLEN (exp, i); j++)
3184 if (compares_alternatives_p (XVECEXP (exp, i, j)))
3185 return 1;
3186 break;
3187 }
3188
3189 return 0;
3190}
3191
3192/* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES. */
3193
3194static void
3195gen_insn (md_rtx_info *info)
3196{
3197 class insn_def *id;
3198 rtx def = info->def;
3199
3200 id = oballoc (class insn_def);
3201 id->next = defs;
3202 defs = id;
3203 id->def = def;
3204 id->loc = info->loc;
3205
3206 switch (GET_CODE (def))
3207 {
3208 case DEFINE_INSN:
3209 id->insn_code = info->index;
3210 id->insn_index = insn_index_number;
3211 id->num_alternatives = count_alternatives (exp: def);
3212 if (id->num_alternatives == 0)
3213 id->num_alternatives = 1;
3214 id->vec_idx = 4;
3215 break;
3216
3217 case DEFINE_PEEPHOLE:
3218 id->insn_code = info->index;
3219 id->insn_index = insn_index_number;
3220 id->num_alternatives = count_alternatives (exp: def);
3221 if (id->num_alternatives == 0)
3222 id->num_alternatives = 1;
3223 id->vec_idx = 3;
3224 break;
3225
3226 case DEFINE_ASM_ATTRIBUTES:
3227 id->insn_code = -1;
3228 id->insn_index = -1;
3229 id->num_alternatives = 1;
3230 id->vec_idx = 0;
3231 got_define_asm_attributes = 1;
3232 break;
3233
3234 default:
3235 gcc_unreachable ();
3236 }
3237}
3238
3239/* Process a DEFINE_DELAY. Validate the vector length, check if annul
3240 true or annul false is specified, and make a `struct delay_desc'. */
3241
3242static void
3243gen_delay (md_rtx_info *info)
3244{
3245 class delay_desc *delay;
3246 int i;
3247
3248 rtx def = info->def;
3249 if (XVECLEN (def, 1) % 3 != 0)
3250 {
3251 error_at (info->loc, "number of elements in DEFINE_DELAY must"
3252 " be multiple of three");
3253 return;
3254 }
3255
3256 for (i = 0; i < XVECLEN (def, 1); i += 3)
3257 {
3258 if (XVECEXP (def, 1, i + 1))
3259 have_annul_true = 1;
3260 if (XVECEXP (def, 1, i + 2))
3261 have_annul_false = 1;
3262 }
3263
3264 delay = oballoc (class delay_desc);
3265 delay->def = def;
3266 delay->num = ++num_delays;
3267 delay->next = delays;
3268 delay->loc = info->loc;
3269 delays = delay;
3270}
3271
3272/* Names of attributes that could be possibly cached. */
3273static const char *cached_attrs[32];
3274/* Number of such attributes. */
3275static int cached_attr_count;
3276/* Bitmasks of possibly cached attributes. */
3277static unsigned int attrs_seen_once, attrs_seen_more_than_once;
3278static unsigned int attrs_to_cache;
3279static unsigned int attrs_cached_inside, attrs_cached_after;
3280
3281/* Finds non-const attributes that could be possibly cached.
3282 When create is TRUE, fills in cached_attrs array.
3283 Computes ATTRS_SEEN_ONCE and ATTRS_SEEN_MORE_THAN_ONCE
3284 bitmasks. */
3285
3286static void
3287find_attrs_to_cache (rtx exp, bool create)
3288{
3289 int i;
3290 const char *name;
3291 class attr_desc *attr;
3292
3293 if (exp == NULL)
3294 return;
3295
3296 switch (GET_CODE (exp))
3297 {
3298 case NOT:
3299 if (GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
3300 find_attrs_to_cache (XEXP (exp, 0), create);
3301 return;
3302
3303 case EQ_ATTR:
3304 name = XSTR (exp, 0);
3305 if (name == alternative_name)
3306 return;
3307 for (i = 0; i < cached_attr_count; i++)
3308 if (name == cached_attrs[i])
3309 {
3310 if ((attrs_seen_once & (1U << i)) != 0)
3311 attrs_seen_more_than_once |= (1U << i);
3312 else
3313 attrs_seen_once |= (1U << i);
3314 return;
3315 }
3316 if (!create)
3317 return;
3318 attr = find_attr (&name, 0);
3319 gcc_assert (attr);
3320 if (attr->is_const)
3321 return;
3322 if (cached_attr_count == 32)
3323 return;
3324 cached_attrs[cached_attr_count] = XSTR (exp, 0);
3325 attrs_seen_once |= (1U << cached_attr_count);
3326 cached_attr_count++;
3327 return;
3328
3329 case AND:
3330 case IOR:
3331 find_attrs_to_cache (XEXP (exp, 0), create);
3332 find_attrs_to_cache (XEXP (exp, 1), create);
3333 return;
3334
3335 case COND:
3336 for (i = 0; i < XVECLEN (exp, 0); i += 2)
3337 find_attrs_to_cache (XVECEXP (exp, 0, i), create);
3338 return;
3339
3340 default:
3341 return;
3342 }
3343}
3344
3345/* Given a piece of RTX, print a C expression to test its truth value to OUTF.
3346 We use AND and IOR both for logical and bit-wise operations, so
3347 interpret them as logical unless they are inside a comparison expression.
3348
3349 An outermost pair of parentheses is emitted around this C expression unless
3350 EMIT_PARENS is false. */
3351
3352/* Interpret AND/IOR as bit-wise operations instead of logical. */
3353#define FLG_BITWISE 1
3354/* Set if cached attribute will be known initialized in else block after
3355 this condition. This is true for LHS of toplevel && and || and
3356 even for RHS of ||, but not for RHS of &&. */
3357#define FLG_AFTER 2
3358/* Set if cached attribute will be known initialized in then block after
3359 this condition. This is true for LHS of toplevel && and || and
3360 even for RHS of &&, but not for RHS of ||. */
3361#define FLG_INSIDE 4
3362/* Cleared when an operand of &&. */
3363#define FLG_OUTSIDE_AND 8
3364
3365static unsigned int
3366write_test_expr (FILE *outf, rtx exp, unsigned int attrs_cached, int flags,
3367 bool emit_parens = true)
3368{
3369 int comparison_operator = 0;
3370 RTX_CODE code;
3371 class attr_desc *attr;
3372
3373 if (emit_parens)
3374 fprintf (stream: outf, format: "(");
3375
3376 code = GET_CODE (exp);
3377 switch (code)
3378 {
3379 /* Binary operators. */
3380 case GEU: case GTU:
3381 case LEU: case LTU:
3382 fprintf (stream: outf, format: "(unsigned) ");
3383 /* Fall through. */
3384
3385 case EQ: case NE:
3386 case GE: case GT:
3387 case LE: case LT:
3388 comparison_operator = FLG_BITWISE;
3389 /* FALLTHRU */
3390
3391 case PLUS: case MINUS: case MULT: case DIV: case MOD:
3392 case AND: case IOR: case XOR:
3393 case ASHIFT: case LSHIFTRT: case ASHIFTRT:
3394 if ((code != AND && code != IOR) || (flags & FLG_BITWISE))
3395 {
3396 flags &= ~(FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND);
3397 write_test_expr (outf, XEXP (exp, 0), attrs_cached,
3398 flags: flags | comparison_operator);
3399 }
3400 else
3401 {
3402 if (code == AND)
3403 flags &= ~FLG_OUTSIDE_AND;
3404 if (GET_CODE (XEXP (exp, 0)) == code
3405 || GET_CODE (XEXP (exp, 0)) == EQ_ATTR
3406 || (GET_CODE (XEXP (exp, 0)) == NOT
3407 && GET_CODE (XEXP (XEXP (exp, 0), 0)) == EQ_ATTR))
3408 attrs_cached
3409 = write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
3410 else
3411 write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
3412 }
3413 switch (code)
3414 {
3415 case EQ:
3416 fprintf (stream: outf, format: " == ");
3417 break;
3418 case NE:
3419 fprintf (stream: outf, format: " != ");
3420 break;
3421 case GE:
3422 fprintf (stream: outf, format: " >= ");
3423 break;
3424 case GT:
3425 fprintf (stream: outf, format: " > ");
3426 break;
3427 case GEU:
3428 fprintf (stream: outf, format: " >= (unsigned) ");
3429 break;
3430 case GTU:
3431 fprintf (stream: outf, format: " > (unsigned) ");
3432 break;
3433 case LE:
3434 fprintf (stream: outf, format: " <= ");
3435 break;
3436 case LT:
3437 fprintf (stream: outf, format: " < ");
3438 break;
3439 case LEU:
3440 fprintf (stream: outf, format: " <= (unsigned) ");
3441 break;
3442 case LTU:
3443 fprintf (stream: outf, format: " < (unsigned) ");
3444 break;
3445 case PLUS:
3446 fprintf (stream: outf, format: " + ");
3447 break;
3448 case MINUS:
3449 fprintf (stream: outf, format: " - ");
3450 break;
3451 case MULT:
3452 fprintf (stream: outf, format: " * ");
3453 break;
3454 case DIV:
3455 fprintf (stream: outf, format: " / ");
3456 break;
3457 case MOD:
3458 fprintf (stream: outf, format: " %% ");
3459 break;
3460 case AND:
3461 if (flags & FLG_BITWISE)
3462 fprintf (stream: outf, format: " & ");
3463 else
3464 fprintf (stream: outf, format: " && ");
3465 break;
3466 case IOR:
3467 if (flags & FLG_BITWISE)
3468 fprintf (stream: outf, format: " | ");
3469 else
3470 fprintf (stream: outf, format: " || ");
3471 break;
3472 case XOR:
3473 fprintf (stream: outf, format: " ^ ");
3474 break;
3475 case ASHIFT:
3476 fprintf (stream: outf, format: " << ");
3477 break;
3478 case LSHIFTRT:
3479 case ASHIFTRT:
3480 fprintf (stream: outf, format: " >> ");
3481 break;
3482 default:
3483 gcc_unreachable ();
3484 }
3485
3486 if (code == AND)
3487 {
3488 /* For if (something && (cached_x = get_attr_x (insn)) == X)
3489 cached_x is only known to be initialized in then block. */
3490 flags &= ~FLG_AFTER;
3491 }
3492 else if (code == IOR)
3493 {
3494 if (flags & FLG_OUTSIDE_AND)
3495 /* For if (something || (cached_x = get_attr_x (insn)) == X)
3496 cached_x is only known to be initialized in else block
3497 and else if conditions. */
3498 flags &= ~FLG_INSIDE;
3499 else
3500 /* For if ((something || (cached_x = get_attr_x (insn)) == X)
3501 && something_else)
3502 cached_x is not know to be initialized anywhere. */
3503 flags &= ~(FLG_AFTER | FLG_INSIDE);
3504 }
3505 if ((code == AND || code == IOR)
3506 && (GET_CODE (XEXP (exp, 1)) == code
3507 || GET_CODE (XEXP (exp, 1)) == EQ_ATTR
3508 || (GET_CODE (XEXP (exp, 1)) == NOT
3509 && GET_CODE (XEXP (XEXP (exp, 1), 0)) == EQ_ATTR)))
3510 {
3511 bool need_parens = true;
3512
3513 /* No need to emit parentheses around the right-hand operand if we are
3514 continuing a chain of && or || (or & or |). */
3515 if (GET_CODE (XEXP (exp, 1)) == code)
3516 need_parens = false;
3517
3518 attrs_cached
3519 = write_test_expr (outf, XEXP (exp, 1), attrs_cached, flags,
3520 emit_parens: need_parens);
3521 }
3522 else
3523 write_test_expr (outf, XEXP (exp, 1), attrs_cached,
3524 flags: flags | comparison_operator);
3525 break;
3526
3527 case NOT:
3528 /* Special-case (not (eq_attrq "alternative" "x")) */
3529 if (! (flags & FLG_BITWISE) && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
3530 {
3531 if (XSTR (XEXP (exp, 0), 0) == alternative_name)
3532 {
3533 fprintf (stream: outf, format: "which_alternative != %s",
3534 XSTR (XEXP (exp, 0), 1));
3535 break;
3536 }
3537
3538 fprintf (stream: outf, format: "! ");
3539 attrs_cached =
3540 write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
3541 break;
3542 }
3543
3544 /* Otherwise, fall through to normal unary operator. */
3545 gcc_fallthrough ();
3546
3547 /* Unary operators. */
3548 case ABS: case NEG:
3549 switch (code)
3550 {
3551 case NOT:
3552 if (flags & FLG_BITWISE)
3553 fprintf (stream: outf, format: "~ ");
3554 else
3555 fprintf (stream: outf, format: "! ");
3556 break;
3557 case ABS:
3558 fprintf (stream: outf, format: "abs ");
3559 break;
3560 case NEG:
3561 fprintf (stream: outf, format: "-");
3562 break;
3563 default:
3564 gcc_unreachable ();
3565 }
3566
3567 flags &= ~(FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND);
3568 write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags);
3569 break;
3570
3571 case EQ_ATTR_ALT:
3572 {
3573 alternative_mask set = XWINT (exp, 0);
3574 int bit = 0;
3575
3576 if (flags & FLG_BITWISE)
3577 fatal ("EQ_ATTR_ALT not valid inside comparison");
3578
3579 if (!set)
3580 fatal ("Empty EQ_ATTR_ALT should be optimized out");
3581
3582 if (!(set & (set - 1)))
3583 {
3584 if (!(set & 0xffffffff))
3585 {
3586 bit += 32;
3587 set >>= 32;
3588 }
3589 if (!(set & 0xffff))
3590 {
3591 bit += 16;
3592 set >>= 16;
3593 }
3594 if (!(set & 0xff))
3595 {
3596 bit += 8;
3597 set >>= 8;
3598 }
3599 if (!(set & 0xf))
3600 {
3601 bit += 4;
3602 set >>= 4;
3603 }
3604 if (!(set & 0x3))
3605 {
3606 bit += 2;
3607 set >>= 2;
3608 }
3609 if (!(set & 1))
3610 bit++;
3611
3612 fprintf (stream: outf, format: "which_alternative %s= %d",
3613 XWINT (exp, 1) ? "!" : "=", bit);
3614 }
3615 else
3616 {
3617 fprintf (stream: outf, format: "%s((1ULL << which_alternative) & %#" PRIx64
3618 "ULL)",
3619 XWINT (exp, 1) ? "!" : "", set);
3620 }
3621 }
3622 break;
3623
3624 /* Comparison test of an attribute with a value. Most of these will
3625 have been removed by optimization. Handle "alternative"
3626 specially and give error if EQ_ATTR present inside a comparison. */
3627 case EQ_ATTR:
3628 if (flags & FLG_BITWISE)
3629 fatal ("EQ_ATTR not valid inside comparison");
3630
3631 if (XSTR (exp, 0) == alternative_name)
3632 {
3633 fprintf (stream: outf, format: "which_alternative == %s", XSTR (exp, 1));
3634 break;
3635 }
3636
3637 attr = find_attr (&XSTR (exp, 0), 0);
3638 gcc_assert (attr);
3639
3640 /* Now is the time to expand the value of a constant attribute. */
3641 if (attr->is_const)
3642 {
3643 write_test_expr (outf,
3644 exp: evaluate_eq_attr (exp, attr,
3645 value: attr->default_val->value,
3646 insn_code: -2, insn_index: -2),
3647 attrs_cached, flags: 0);
3648 }
3649 else
3650 {
3651 int i;
3652 for (i = 0; i < cached_attr_count; i++)
3653 if (attr->name == cached_attrs[i])
3654 break;
3655 if (i < cached_attr_count && (attrs_cached & (1U << i)) != 0)
3656 fprintf (stream: outf, format: "cached_%s", attr->name);
3657 else if (i < cached_attr_count && (attrs_to_cache & (1U << i)) != 0)
3658 {
3659 fprintf (stream: outf, format: "(cached_%s = get_attr_%s (insn))",
3660 attr->name, attr->name);
3661 if (flags & FLG_AFTER)
3662 attrs_cached_after |= (1U << i);
3663 if (flags & FLG_INSIDE)
3664 attrs_cached_inside |= (1U << i);
3665 attrs_cached |= (1U << i);
3666 }
3667 else
3668 fprintf (stream: outf, format: "get_attr_%s (insn)", attr->name);
3669 fprintf (stream: outf, format: " == ");
3670 write_attr_valueq (outf, attr, XSTR (exp, 1));
3671 }
3672 break;
3673
3674 /* Comparison test of flags for define_delays. */
3675 case ATTR_FLAG:
3676 if (flags & FLG_BITWISE)
3677 fatal ("ATTR_FLAG not valid inside comparison");
3678 fprintf (stream: outf, format: "(flags & ATTR_FLAG_%s) != 0", XSTR (exp, 0));
3679 break;
3680
3681 /* See if an operand matches a predicate. */
3682 case MATCH_OPERAND:
3683 /* If only a mode is given, just ensure the mode matches the operand.
3684 If neither a mode nor predicate is given, error. */
3685 if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0')
3686 {
3687 if (GET_MODE (exp) == VOIDmode)
3688 fatal ("null MATCH_OPERAND specified as test");
3689 else
3690 fprintf (stream: outf, format: "GET_MODE (operands[%d]) == %smode",
3691 XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
3692 }
3693 else
3694 fprintf (stream: outf, format: "%s (operands[%d], %smode)",
3695 XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
3696 break;
3697
3698 /* Constant integer. */
3699 case CONST_INT:
3700 fprintf (stream: outf, HOST_WIDE_INT_PRINT_DEC, XWINT (exp, 0));
3701 break;
3702
3703 case MATCH_TEST:
3704 rtx_reader_ptr->fprint_c_condition (outf, XSTR (exp, 0));
3705 if (flags & FLG_BITWISE)
3706 fprintf (stream: outf, format: " != 0");
3707 break;
3708
3709 /* A random C expression. */
3710 case SYMBOL_REF:
3711 rtx_reader_ptr->fprint_c_condition (outf, XSTR (exp, 0));
3712 break;
3713
3714 /* The address of the branch target. */
3715 case MATCH_DUP:
3716 fprintf (stream: outf,
3717 format: "INSN_ADDRESSES_SET_P () ? INSN_ADDRESSES (INSN_UID (GET_CODE (operands[%d]) == LABEL_REF ? XEXP (operands[%d], 0) : operands[%d])) : 0",
3718 XINT (exp, 0), XINT (exp, 0), XINT (exp, 0));
3719 break;
3720
3721 case PC:
3722 /* The address of the current insn. We implement this actually as the
3723 address of the current insn for backward branches, but the last
3724 address of the next insn for forward branches, and both with
3725 adjustments that account for the worst-case possible stretching of
3726 intervening alignments between this insn and its destination. */
3727 fprintf (stream: outf, format: "insn_current_reference_address (insn)");
3728 break;
3729
3730 case CONST_STRING:
3731 fprintf (stream: outf, format: "%s", XSTR (exp, 0));
3732 break;
3733
3734 case IF_THEN_ELSE:
3735 write_test_expr (outf, XEXP (exp, 0), attrs_cached, flags: 0);
3736 fprintf (stream: outf, format: " ? ");
3737 write_test_expr (outf, XEXP (exp, 1), attrs_cached, FLG_BITWISE);
3738 fprintf (stream: outf, format: " : ");
3739 write_test_expr (outf, XEXP (exp, 2), attrs_cached, FLG_BITWISE);
3740 break;
3741
3742 default:
3743 fatal ("bad RTX code `%s' in attribute calculation\n",
3744 GET_RTX_NAME (code));
3745 }
3746
3747 if (emit_parens)
3748 fprintf (stream: outf, format: ")");
3749
3750 return attrs_cached;
3751}
3752
3753/* Given an attribute value expression, return the maximum value that
3754 might be evaluated. Return INT_MAX if the value can't be
3755 calculated by this function. */
3756
3757static int
3758max_attr_value (rtx exp)
3759{
3760 int current_max;
3761 int i, n;
3762
3763 switch (GET_CODE (exp))
3764 {
3765 case CONST_STRING:
3766 current_max = atoi (XSTR (exp, 0));
3767 break;
3768
3769 case CONST_INT:
3770 current_max = INTVAL (exp);
3771 break;
3772
3773 case PLUS:
3774 current_max = max_attr_value (XEXP (exp, 0));
3775 if (current_max != INT_MAX)
3776 {
3777 n = current_max;
3778 current_max = max_attr_value (XEXP (exp, 1));
3779 if (current_max != INT_MAX)
3780 current_max += n;
3781 }
3782 break;
3783
3784 case MINUS:
3785 current_max = max_attr_value (XEXP (exp, 0));
3786 if (current_max != INT_MAX)
3787 {
3788 n = current_max;
3789 current_max = min_attr_value (XEXP (exp, 1));
3790 if (current_max != INT_MAX)
3791 current_max = n - current_max;
3792 }
3793 break;
3794
3795 case MULT:
3796 current_max = max_attr_value (XEXP (exp, 0));
3797 if (current_max != INT_MAX)
3798 {
3799 n = current_max;
3800 current_max = max_attr_value (XEXP (exp, 1));
3801 if (current_max != INT_MAX)
3802 current_max *= n;
3803 }
3804 break;
3805
3806 case COND:
3807 current_max = max_attr_value (XEXP (exp, 1));
3808 for (i = 0; i < XVECLEN (exp, 0); i += 2)
3809 {
3810 n = max_attr_value (XVECEXP (exp, 0, i + 1));
3811 if (n > current_max)
3812 current_max = n;
3813 }
3814 break;
3815
3816 case IF_THEN_ELSE:
3817 current_max = max_attr_value (XEXP (exp, 1));
3818 n = max_attr_value (XEXP (exp, 2));
3819 if (n > current_max)
3820 current_max = n;
3821 break;
3822
3823 default:
3824 current_max = INT_MAX;
3825 break;
3826 }
3827
3828 return current_max;
3829}
3830
3831/* Given an attribute value expression, return the minimum value that
3832 might be evaluated. Return INT_MAX if the value can't be
3833 calculated by this function. Note that when this function can
3834 calculate one value inside IF_THEN_ELSE or some but not all values
3835 inside COND, then it returns the minimum among those values it can
3836 calculate. */
3837
3838static int
3839min_attr_value (rtx exp)
3840{
3841 int current_min;
3842 int i, n;
3843
3844 switch (GET_CODE (exp))
3845 {
3846 case CONST_STRING:
3847 current_min = atoi (XSTR (exp, 0));
3848 break;
3849
3850 case CONST_INT:
3851 current_min = INTVAL (exp);
3852 break;
3853
3854 case PLUS:
3855 current_min = min_attr_value (XEXP (exp, 0));
3856 if (current_min != INT_MAX)
3857 {
3858 n = current_min;
3859 current_min = min_attr_value (XEXP (exp, 1));
3860 if (current_min != INT_MAX)
3861 current_min += n;
3862 }
3863 break;
3864
3865 case MINUS:
3866 current_min = min_attr_value (XEXP (exp, 0));
3867 if (current_min != INT_MAX)
3868 {
3869 n = current_min;
3870 current_min = max_attr_value (XEXP (exp, 1));
3871 if (current_min != INT_MAX)
3872 current_min = n - current_min;
3873 }
3874 break;
3875
3876 case MULT:
3877 current_min = min_attr_value (XEXP (exp, 0));
3878 if (current_min != INT_MAX)
3879 {
3880 n = current_min;
3881 current_min = min_attr_value (XEXP (exp, 1));
3882 if (current_min != INT_MAX)
3883 current_min *= n;
3884 }
3885 break;
3886
3887 case COND:
3888 current_min = min_attr_value (XEXP (exp, 1));
3889 for (i = 0; i < XVECLEN (exp, 0); i += 2)
3890 {
3891 n = min_attr_value (XVECEXP (exp, 0, i + 1));
3892 if (n < current_min)
3893 current_min = n;
3894 }
3895 break;
3896
3897 case IF_THEN_ELSE:
3898 current_min = min_attr_value (XEXP (exp, 1));
3899 n = min_attr_value (XEXP (exp, 2));
3900 if (n < current_min)
3901 current_min = n;
3902 break;
3903
3904 default:
3905 current_min = INT_MAX;
3906 break;
3907 }
3908
3909 return current_min;
3910}
3911
3912/* Given an attribute value expression, return the alignment of values.
3913 Return 0 if EXP is known to be zero, and 1 if the value can't be
3914 calculated by this function. */
3915
3916static unsigned int
3917attr_value_alignment (rtx exp)
3918{
3919 unsigned int current_or;
3920 int i;
3921
3922 switch (GET_CODE (exp))
3923 {
3924 case CONST_STRING:
3925 current_or = atoi (XSTR (exp, 0));
3926 break;
3927
3928 case CONST_INT:
3929 current_or = INTVAL (exp);
3930 break;
3931
3932 case PLUS:
3933 case MINUS:
3934 current_or = attr_value_alignment (XEXP (exp, 0));
3935 current_or |= attr_value_alignment (XEXP (exp, 1));
3936 break;
3937
3938 case MULT:
3939 current_or = attr_value_alignment (XEXP (exp, 0));
3940 current_or *= attr_value_alignment (XEXP (exp, 1));
3941 break;
3942
3943 case COND:
3944 current_or = attr_value_alignment (XEXP (exp, 1));
3945 for (i = 0; i < XVECLEN (exp, 0); i += 2)
3946 current_or |= attr_value_alignment (XVECEXP (exp, 0, i + 1));
3947 break;
3948
3949 case IF_THEN_ELSE:
3950 current_or = attr_value_alignment (XEXP (exp, 1));
3951 current_or |= attr_value_alignment (XEXP (exp, 2));
3952 break;
3953
3954 default:
3955 current_or = 1;
3956 break;
3957 }
3958
3959 return current_or & -current_or;
3960}
3961
3962/* Scan an attribute value, possibly a conditional, and record what actions
3963 will be required to do any conditional tests in it.
3964
3965 Specifically, set
3966 `must_extract' if we need to extract the insn operands
3967 `must_constrain' if we must compute `which_alternative'
3968 `address_used' if an address expression was used
3969 `length_used' if an (eq_attr "length" ...) was used
3970 */
3971
3972static void
3973walk_attr_value (rtx exp)
3974{
3975 int i, j;
3976 const char *fmt;
3977 RTX_CODE code;
3978
3979 if (exp == NULL)
3980 return;
3981
3982 code = GET_CODE (exp);
3983 switch (code)
3984 {
3985 case SYMBOL_REF:
3986 if (! ATTR_IND_SIMPLIFIED_P (exp))
3987 /* Since this is an arbitrary expression, it can look at anything.
3988 However, constant expressions do not depend on any particular
3989 insn. */
3990 must_extract = must_constrain = 1;
3991 return;
3992
3993 case MATCH_OPERAND:
3994 must_extract = 1;
3995 return;
3996
3997 case MATCH_TEST:
3998 case EQ_ATTR_ALT:
3999 must_extract = must_constrain = 1;
4000 break;
4001
4002 case EQ_ATTR:
4003 if (XSTR (exp, 0) == alternative_name)
4004 must_extract = must_constrain = 1;
4005 else if (strcmp_check (XSTR (exp, 0), length_str) == 0)
4006 length_used = 1;
4007 return;
4008
4009 case MATCH_DUP:
4010 must_extract = 1;
4011 address_used = 1;
4012 return;
4013
4014 case PC:
4015 address_used = 1;
4016 return;
4017
4018 case ATTR_FLAG:
4019 return;
4020
4021 default:
4022 break;
4023 }
4024
4025 for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
4026 switch (*fmt++)
4027 {
4028 case 'e':
4029 case 'u':
4030 walk_attr_value (XEXP (exp, i));
4031 break;
4032
4033 case 'E':
4034 if (XVEC (exp, i) != NULL)
4035 for (j = 0; j < XVECLEN (exp, i); j++)
4036 walk_attr_value (XVECEXP (exp, i, j));
4037 break;
4038 }
4039}
4040
4041/* Write out a function to obtain the attribute for a given INSN. */
4042
4043static void
4044write_attr_get (FILE *outf, class attr_desc *attr)
4045{
4046 struct attr_value *av, *common_av;
4047 int i, j;
4048
4049 /* Find the most used attribute value. Handle that as the `default' of the
4050 switch we will generate. */
4051 common_av = find_most_used (attr);
4052
4053 /* Write out start of function, then all values with explicit `case' lines,
4054 then a `default', then the value with the most uses. */
4055 if (attr->enum_name)
4056 fprintf (stream: outf, format: "enum %s\n", attr->enum_name);
4057 else if (!attr->is_numeric)
4058 fprintf (stream: outf, format: "enum attr_%s\n", attr->name);
4059 else
4060 fprintf (stream: outf, format: "int\n");
4061
4062 /* If the attribute name starts with a star, the remainder is the name of
4063 the subroutine to use, instead of `get_attr_...'. */
4064 if (attr->name[0] == '*')
4065 fprintf (stream: outf, format: "%s (rtx_insn *insn ATTRIBUTE_UNUSED)\n", &attr->name[1]);
4066 else if (attr->is_const == 0)
4067 fprintf (stream: outf, format: "get_attr_%s (rtx_insn *insn ATTRIBUTE_UNUSED)\n", attr->name);
4068 else
4069 {
4070 fprintf (stream: outf, format: "get_attr_%s (void)\n", attr->name);
4071 fprintf (stream: outf, format: "{\n");
4072
4073 for (av = attr->first_value; av; av = av->next)
4074 if (av->num_insns == 1)
4075 write_attr_set (outf, attr, 2, av->value, "return", ";",
4076 true_rtx, av->first_insn->def->insn_code,
4077 av->first_insn->def->insn_index, 0);
4078 else if (av->num_insns != 0)
4079 write_attr_set (outf, attr, 2, av->value, "return", ";",
4080 true_rtx, -2, 0, 0);
4081
4082 fprintf (stream: outf, format: "}\n\n");
4083 return;
4084 }
4085
4086 fprintf (stream: outf, format: "{\n");
4087
4088 /* Find attributes that are worth caching in the conditions. */
4089 cached_attr_count = 0;
4090 attrs_seen_more_than_once = 0;
4091 for (av = attr->first_value; av; av = av->next)
4092 {
4093 attrs_seen_once = 0;
4094 find_attrs_to_cache (exp: av->value, create: true);
4095 }
4096 /* Remove those that aren't worth caching from the array. */
4097 for (i = 0, j = 0; i < cached_attr_count; i++)
4098 if ((attrs_seen_more_than_once & (1U << i)) != 0)
4099 {
4100 const char *name = cached_attrs[i];
4101 class attr_desc *cached_attr;
4102 if (i != j)
4103 cached_attrs[j] = name;
4104 cached_attr = find_attr (&name, 0);
4105 gcc_assert (cached_attr && cached_attr->is_const == 0);
4106 if (cached_attr->enum_name)
4107 fprintf (stream: outf, format: " enum %s", cached_attr->enum_name);
4108 else if (!cached_attr->is_numeric)
4109 fprintf (stream: outf, format: " enum attr_%s", cached_attr->name);
4110 else
4111 fprintf (stream: outf, format: " int");
4112 fprintf (stream: outf, format: " cached_%s ATTRIBUTE_UNUSED;\n", name);
4113 j++;
4114 }
4115 cached_attr_count = j;
4116 if (cached_attr_count)
4117 fprintf (stream: outf, format: "\n");
4118
4119 fprintf (stream: outf, format: " switch (recog_memoized (insn))\n");
4120 fprintf (stream: outf, format: " {\n");
4121
4122 for (av = attr->first_value; av; av = av->next)
4123 if (av != common_av)
4124 write_attr_case (outf, attr, av, 1, "return", ";", 4, true_rtx);
4125
4126 write_attr_case (outf, attr, common_av, 0, "return", ";", 4, true_rtx);
4127 fprintf (stream: outf, format: " }\n}\n\n");
4128 cached_attr_count = 0;
4129}
4130
4131/* Given an AND tree of known true terms (because we are inside an `if' with
4132 that as the condition or are in an `else' clause) and an expression,
4133 replace any known true terms with TRUE. Use `simplify_and_tree' to do
4134 the bulk of the work. */
4135
4136static rtx
4137eliminate_known_true (rtx known_true, rtx exp, int insn_code, int insn_index)
4138{
4139 rtx term;
4140
4141 known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
4142
4143 if (GET_CODE (known_true) == AND)
4144 {
4145 exp = eliminate_known_true (XEXP (known_true, 0), exp,
4146 insn_code, insn_index);
4147 exp = eliminate_known_true (XEXP (known_true, 1), exp,
4148 insn_code, insn_index);
4149 }
4150 else
4151 {
4152 term = known_true;
4153 exp = simplify_and_tree (exp, pterm: &term, insn_code, insn_index);
4154 }
4155
4156 return exp;
4157}
4158
4159/* Write out a series of tests and assignment statements to perform tests and
4160 sets of an attribute value. We are passed an indentation amount and prefix
4161 and suffix strings to write around each attribute value (e.g., "return"
4162 and ";"). */
4163
4164static void
4165write_attr_set (FILE *outf, class attr_desc *attr, int indent, rtx value,
4166 const char *prefix, const char *suffix, rtx known_true,
4167 int insn_code, int insn_index, unsigned int attrs_cached)
4168{
4169 if (GET_CODE (value) == COND)
4170 {
4171 /* Assume the default value will be the default of the COND unless we
4172 find an always true expression. */
4173 rtx default_val = XEXP (value, 1);
4174 rtx our_known_true = known_true;
4175 rtx newexp;
4176 int first_if = 1;
4177 int i;
4178
4179 if (cached_attr_count)
4180 {
4181 attrs_seen_once = 0;
4182 attrs_seen_more_than_once = 0;
4183 for (i = 0; i < XVECLEN (value, 0); i += 2)
4184 find_attrs_to_cache (XVECEXP (value, 0, i), create: false);
4185 attrs_to_cache |= attrs_seen_more_than_once;
4186 }
4187
4188 for (i = 0; i < XVECLEN (value, 0); i += 2)
4189 {
4190 rtx testexp;
4191 rtx inner_true;
4192
4193 /* Reset our_known_true after some time to not accumulate
4194 too much cruft (slowing down genattrtab). */
4195 if ((i & 31) == 0)
4196 our_known_true = known_true;
4197 testexp = eliminate_known_true (known_true: our_known_true,
4198 XVECEXP (value, 0, i),
4199 insn_code, insn_index);
4200 newexp = attr_rtx (code: NOT, testexp);
4201 newexp = insert_right_side (code: AND, exp: our_known_true, term: newexp,
4202 insn_code, insn_index);
4203
4204 /* If the test expression is always true or if the next `known_true'
4205 expression is always false, this is the last case, so break
4206 out and let this value be the `else' case. */
4207 if (testexp == true_rtx || newexp == false_rtx)
4208 {
4209 default_val = XVECEXP (value, 0, i + 1);
4210 break;
4211 }
4212
4213 /* Compute the expression to pass to our recursive call as being
4214 known true. */
4215 inner_true = insert_right_side (code: AND, exp: our_known_true,
4216 term: testexp, insn_code, insn_index);
4217
4218 /* If this is always false, skip it. */
4219 if (inner_true == false_rtx)
4220 continue;
4221
4222 attrs_cached_inside = attrs_cached;
4223 attrs_cached_after = attrs_cached;
4224 write_indent (outf, indent);
4225 fprintf (stream: outf, format: "%sif ", first_if ? "" : "else ");
4226 first_if = 0;
4227 write_test_expr (outf, exp: testexp, attrs_cached,
4228 flags: (FLG_AFTER | FLG_INSIDE | FLG_OUTSIDE_AND));
4229 attrs_cached = attrs_cached_after;
4230 fprintf (stream: outf, format: "\n");
4231 write_indent (outf, indent + 2);
4232 fprintf (stream: outf, format: "{\n");
4233
4234 write_attr_set (outf, attr, indent: indent + 4,
4235 XVECEXP (value, 0, i + 1), prefix, suffix,
4236 known_true: inner_true, insn_code, insn_index,
4237 attrs_cached: attrs_cached_inside);
4238 write_indent (outf, indent + 2);
4239 fprintf (stream: outf, format: "}\n");
4240 our_known_true = newexp;
4241 }
4242
4243 if (! first_if)
4244 {
4245 write_indent (outf, indent);
4246 fprintf (stream: outf, format: "else\n");
4247 write_indent (outf, indent + 2);
4248 fprintf (stream: outf, format: "{\n");
4249 }
4250
4251 write_attr_set (outf, attr, indent: first_if ? indent : indent + 4, value: default_val,
4252 prefix, suffix, known_true: our_known_true, insn_code, insn_index,
4253 attrs_cached);
4254
4255 if (! first_if)
4256 {
4257 write_indent (outf, indent + 2);
4258 fprintf (stream: outf, format: "}\n");
4259 }
4260 }
4261 else
4262 {
4263 write_indent (outf, indent);
4264 fprintf (stream: outf, format: "%s ", prefix);
4265 write_attr_value (outf, attr, value);
4266 fprintf (stream: outf, format: "%s\n", suffix);
4267 }
4268}
4269
4270/* Write a series of case statements for every instruction in list IE.
4271 INDENT is the amount of indentation to write before each case. */
4272
4273static void
4274write_insn_cases (FILE *outf, struct insn_ent *ie, int indent)
4275{
4276 for (; ie != 0; ie = ie->next)
4277 if (ie->def->insn_code != -1)
4278 {
4279 write_indent (outf, indent);
4280 if (GET_CODE (ie->def->def) == DEFINE_PEEPHOLE)
4281 fprintf (stream: outf, format: "case %d: /* define_peephole, %s:%d */\n",
4282 ie->def->insn_code, ie->def->loc.filename,
4283 ie->def->loc.lineno);
4284 else
4285 fprintf (stream: outf, format: "case %d: /* %s */\n",
4286 ie->def->insn_code, XSTR (ie->def->def, 0));
4287 }
4288}
4289
4290/* Write out the computation for one attribute value. */
4291
4292static void
4293write_attr_case (FILE *outf, class attr_desc *attr, struct attr_value *av,
4294 int write_case_lines, const char *prefix, const char *suffix,
4295 int indent, rtx known_true)
4296{
4297 if (av->num_insns == 0)
4298 return;
4299
4300 if (av->has_asm_insn)
4301 {
4302 write_indent (outf, indent);
4303 fprintf (stream: outf, format: "case -1:\n");
4304 write_indent (outf, indent + 2);
4305 fprintf (stream: outf, format: "if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
4306 write_indent (outf, indent + 2);
4307 fprintf (stream: outf, format: " && asm_noperands (PATTERN (insn)) < 0)\n");
4308 write_indent (outf, indent + 2);
4309 fprintf (stream: outf, format: " fatal_insn_not_found (insn);\n");
4310 write_indent (outf, indent + 2);
4311 fprintf (stream: outf, format: "/* FALLTHRU */\n");
4312 }
4313
4314 if (write_case_lines)
4315 write_insn_cases (outf, ie: av->first_insn, indent);
4316 else
4317 {
4318 write_indent (outf, indent);
4319 fprintf (stream: outf, format: "default:\n");
4320 }
4321
4322 /* See what we have to do to output this value. */
4323 must_extract = must_constrain = address_used = 0;
4324 walk_attr_value (exp: av->value);
4325
4326 if (must_constrain)
4327 {
4328 write_indent (outf, indent + 2);
4329 fprintf (stream: outf, format: "extract_constrain_insn_cached (insn);\n");
4330 }
4331 else if (must_extract)
4332 {
4333 write_indent (outf, indent + 2);
4334 fprintf (stream: outf, format: "extract_insn_cached (insn);\n");
4335 }
4336
4337 attrs_to_cache = 0;
4338 if (av->num_insns == 1)
4339 write_attr_set (outf, attr, indent: indent + 2, value: av->value, prefix, suffix,
4340 known_true, insn_code: av->first_insn->def->insn_code,
4341 insn_index: av->first_insn->def->insn_index, attrs_cached: 0);
4342 else
4343 write_attr_set (outf, attr, indent: indent + 2, value: av->value, prefix, suffix,
4344 known_true, insn_code: -2, insn_index: 0, attrs_cached: 0);
4345
4346 if (!startswith (str: prefix, prefix: "return"))
4347 {
4348 write_indent (outf, indent + 2);
4349 fprintf (stream: outf, format: "break;\n");
4350 }
4351 fprintf (stream: outf, format: "\n");
4352}
4353
4354/* Utilities to write in various forms. */
4355
4356static void
4357write_attr_valueq (FILE *outf, class attr_desc *attr, const char *s)
4358{
4359 if (attr->is_numeric)
4360 {
4361 int num = atoi (nptr: s);
4362
4363 fprintf (stream: outf, format: "%d", num);
4364
4365 if (num > 9 || num < 0)
4366 fprintf (stream: outf, format: " /* %#x */", num);
4367 }
4368 else
4369 {
4370 write_upcase (outf, attr->enum_name ? attr->enum_name : attr->name);
4371 fprintf (stream: outf, format: "_");
4372 write_upcase (outf, s);
4373 }
4374}
4375
4376static void
4377write_attr_value (FILE *outf, class attr_desc *attr, rtx value)
4378{
4379 int op;
4380
4381 switch (GET_CODE (value))
4382 {
4383 case CONST_STRING:
4384 write_attr_valueq (outf, attr, XSTR (value, 0));
4385 break;
4386
4387 case CONST_INT:
4388 fprintf (stream: outf, HOST_WIDE_INT_PRINT_DEC, INTVAL (value));
4389 break;
4390
4391 case SYMBOL_REF:
4392 rtx_reader_ptr->fprint_c_condition (outf, XSTR (value, 0));
4393 break;
4394
4395 case ATTR:
4396 {
4397 class attr_desc *attr2 = find_attr (&XSTR (value, 0), 0);
4398 if (attr->enum_name)
4399 fprintf (stream: outf, format: "(enum %s)", attr->enum_name);
4400 else if (!attr->is_numeric)
4401 fprintf (stream: outf, format: "(enum attr_%s)", attr->name);
4402 else if (!attr2->is_numeric)
4403 fprintf (stream: outf, format: "(int)");
4404
4405 fprintf (stream: outf, format: "get_attr_%s (%s)", attr2->name,
4406 (attr2->is_const ? "" : "insn"));
4407 }
4408 break;
4409
4410 case PLUS:
4411 op = '+';
4412 goto do_operator;
4413 case MINUS:
4414 op = '-';
4415 goto do_operator;
4416 case MULT:
4417 op = '*';
4418 goto do_operator;
4419 case DIV:
4420 op = '/';
4421 goto do_operator;
4422 case MOD:
4423 op = '%';
4424 goto do_operator;
4425
4426 do_operator:
4427 fprintf (stream: outf, format: "(");
4428 write_attr_value (outf, attr, XEXP (value, 0));
4429 fprintf (stream: outf, format: " %c ", op);
4430 write_attr_value (outf, attr, XEXP (value, 1));
4431 fprintf (stream: outf, format: ")");
4432 break;
4433
4434 case IF_THEN_ELSE:
4435 fprintf (stream: outf, format: "(");
4436 write_test_expr (outf, XEXP (value, 0), attrs_cached: 0, flags: 0, emit_parens: false);
4437 fprintf (stream: outf, format: " ? ");
4438 write_attr_value (outf, attr, XEXP (value, 1));
4439 fprintf (stream: outf, format: " : ");
4440 write_attr_value (outf, attr, XEXP (value, 2));
4441 fprintf (stream: outf, format: ")");
4442 break;
4443
4444 default:
4445 gcc_unreachable ();
4446 }
4447}
4448
4449static void
4450write_upcase (FILE *outf, const char *str)
4451{
4452 while (*str)
4453 {
4454 /* The argument of TOUPPER should not have side effects. */
4455 fputc (TOUPPER (*str), outf);
4456 str++;
4457 }
4458}
4459
4460static void
4461write_indent (FILE *outf, int indent)
4462{
4463 for (; indent > 8; indent -= 8)
4464 fprintf (stream: outf, format: "\t");
4465
4466 for (; indent; indent--)
4467 fprintf (stream: outf, format: " ");
4468}
4469
4470/* If the target does not have annul-true or annul-false delay slots, this
4471 function will create a dummy eligible_for function on OUTF which always
4472 returns false. KIND will be annul_true or annul_false. */
4473
4474static void
4475write_dummy_eligible_delay (FILE *outf, const char *kind)
4476{
4477 /* Write function prelude. */
4478
4479 fprintf (stream: outf, format: "int\n");
4480 fprintf (stream: outf, format: "eligible_for_%s (rtx_insn *delay_insn ATTRIBUTE_UNUSED,\n"
4481 " int slot ATTRIBUTE_UNUSED,\n"
4482 " rtx_insn *candidate_insn ATTRIBUTE_UNUSED,\n"
4483 " int flags ATTRIBUTE_UNUSED)\n",
4484 kind);
4485 fprintf (stream: outf, format: "{\n");
4486 fprintf (stream: outf, format: " return 0;\n");
4487 fprintf (stream: outf, format: "}\n\n");
4488}
4489
4490/* Write a subroutine that is given an insn that requires a delay slot, a
4491 delay slot ordinal, and a candidate insn. It returns nonzero if the
4492 candidate can be placed in the specified delay slot of the insn.
4493
4494 We can write as many as three subroutines. `eligible_for_delay'
4495 handles normal delay slots, `eligible_for_annul_true' indicates that
4496 the specified insn can be annulled if the branch is true, and likewise
4497 for `eligible_for_annul_false'.
4498
4499 KIND is a string distinguishing these three cases ("delay", "annul_true",
4500 or "annul_false"). */
4501
4502static void
4503write_eligible_delay (FILE *outf, const char *kind)
4504{
4505 class delay_desc *delay;
4506 int max_slots;
4507 char str[50];
4508 const char *pstr;
4509 class attr_desc *attr;
4510 struct attr_value *av, *common_av;
4511 int i;
4512
4513 /* Compute the maximum number of delay slots required. We use the delay
4514 ordinal times this number plus one, plus the slot number as an index into
4515 the appropriate predicate to test. */
4516
4517 for (delay = delays, max_slots = 0; delay; delay = delay->next)
4518 if (XVECLEN (delay->def, 1) / 3 > max_slots)
4519 max_slots = XVECLEN (delay->def, 1) / 3;
4520
4521 /* Write function prelude. */
4522
4523 fprintf (stream: outf, format: "int\n");
4524 fprintf (stream: outf, format: "eligible_for_%s (rtx_insn *delay_insn ATTRIBUTE_UNUSED, int slot, \n"
4525 " rtx_insn *candidate_insn, int flags ATTRIBUTE_UNUSED)\n",
4526 kind);
4527 fprintf (stream: outf, format: "{\n");
4528 fprintf (stream: outf, format: " rtx_insn *insn ATTRIBUTE_UNUSED;\n");
4529 fprintf (stream: outf, format: "\n");
4530 fprintf (stream: outf, format: " if (num_delay_slots (delay_insn) == 0)\n");
4531 fprintf (stream: outf, format: " return 0;");
4532 fprintf (stream: outf, format: "\n");
4533 fprintf (stream: outf, format: " gcc_assert (slot < %d);\n", max_slots);
4534 fprintf (stream: outf, format: "\n");
4535 /* Allow dbr_schedule to pass labels, etc. This can happen if try_split
4536 converts a compound instruction into a loop. */
4537 fprintf (stream: outf, format: " if (!INSN_P (candidate_insn))\n");
4538 fprintf (stream: outf, format: " return 0;\n");
4539 fprintf (stream: outf, format: "\n");
4540
4541 /* If more than one delay type, find out which type the delay insn is. */
4542
4543 if (num_delays > 1)
4544 {
4545 attr = find_attr (&delay_type_str, 0);
4546 gcc_assert (attr);
4547 common_av = find_most_used (attr);
4548
4549 fprintf (stream: outf, format: " insn = delay_insn;\n");
4550 fprintf (stream: outf, format: " switch (recog_memoized (insn))\n");
4551 fprintf (stream: outf, format: " {\n");
4552
4553 sprintf (s: str, format: " * %d;\n break;", max_slots);
4554 for (av = attr->first_value; av; av = av->next)
4555 if (av != common_av)
4556 write_attr_case (outf, attr, av, write_case_lines: 1, prefix: "slot +=", suffix: str, indent: 4, known_true: true_rtx);
4557
4558 write_attr_case (outf, attr, av: common_av, write_case_lines: 0, prefix: "slot +=", suffix: str, indent: 4, known_true: true_rtx);
4559 fprintf (stream: outf, format: " }\n\n");
4560
4561 /* Ensure matched. Otherwise, shouldn't have been called. */
4562 fprintf (stream: outf, format: " gcc_assert (slot >= %d);\n\n", max_slots);
4563 }
4564
4565 /* If just one type of delay slot, write simple switch. */
4566 if (num_delays == 1 && max_slots == 1)
4567 {
4568 fprintf (stream: outf, format: " insn = candidate_insn;\n");
4569 fprintf (stream: outf, format: " switch (recog_memoized (insn))\n");
4570 fprintf (stream: outf, format: " {\n");
4571
4572 attr = find_attr (&delay_1_0_str, 0);
4573 gcc_assert (attr);
4574 common_av = find_most_used (attr);
4575
4576 for (av = attr->first_value; av; av = av->next)
4577 if (av != common_av)
4578 write_attr_case (outf, attr, av, write_case_lines: 1, prefix: "return", suffix: ";", indent: 4, known_true: true_rtx);
4579
4580 write_attr_case (outf, attr, av: common_av, write_case_lines: 0, prefix: "return", suffix: ";", indent: 4, known_true: true_rtx);
4581 fprintf (stream: outf, format: " }\n");
4582 }
4583
4584 else
4585 {
4586 /* Write a nested CASE. The first indicates which condition we need to
4587 test, and the inner CASE tests the condition. */
4588 fprintf (stream: outf, format: " insn = candidate_insn;\n");
4589 fprintf (stream: outf, format: " switch (slot)\n");
4590 fprintf (stream: outf, format: " {\n");
4591
4592 for (delay = delays; delay; delay = delay->next)
4593 for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
4594 {
4595 fprintf (stream: outf, format: " case %d:\n",
4596 (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
4597 fprintf (stream: outf, format: " switch (recog_memoized (insn))\n");
4598 fprintf (stream: outf, format: "\t{\n");
4599
4600 sprintf (s: str, format: "*%s_%d_%d", kind, delay->num, i / 3);
4601 pstr = str;
4602 attr = find_attr (&pstr, 0);
4603 gcc_assert (attr);
4604 common_av = find_most_used (attr);
4605
4606 for (av = attr->first_value; av; av = av->next)
4607 if (av != common_av)
4608 write_attr_case (outf, attr, av, write_case_lines: 1, prefix: "return", suffix: ";", indent: 8, known_true: true_rtx);
4609
4610 write_attr_case (outf, attr, av: common_av, write_case_lines: 0, prefix: "return", suffix: ";", indent: 8, known_true: true_rtx);
4611 fprintf (stream: outf, format: " }\n");
4612 }
4613
4614 fprintf (stream: outf, format: " default:\n");
4615 fprintf (stream: outf, format: " gcc_unreachable ();\n");
4616 fprintf (stream: outf, format: " }\n");
4617 }
4618
4619 fprintf (stream: outf, format: "}\n\n");
4620}
4621
4622/* This page contains miscellaneous utility routines. */
4623
4624/* Given a pointer to a (char *), return a malloc'ed string containing the
4625 next comma-separated element. Advance the pointer to after the string
4626 scanned, or the end-of-string. Return NULL if at end of string. */
4627
4628static char *
4629next_comma_elt (const char **pstr)
4630{
4631 const char *start;
4632
4633 start = scan_comma_elt (pstr);
4634
4635 if (start == NULL)
4636 return NULL;
4637
4638 return attr_string (str: start, len: *pstr - start);
4639}
4640
4641/* Return a `class attr_desc' pointer for a given named attribute. If CREATE
4642 is nonzero, build a new attribute, if one does not exist. *NAME_P is
4643 replaced by a pointer to a canonical copy of the string. */
4644
4645static class attr_desc *
4646find_attr (const char **name_p, int create)
4647{
4648 class attr_desc *attr;
4649 int index;
4650 const char *name = *name_p;
4651
4652 /* Before we resort to using `strcmp', see if the string address matches
4653 anywhere. In most cases, it should have been canonicalized to do so. */
4654 if (name == alternative_name)
4655 return NULL;
4656
4657 index = name[0] & (MAX_ATTRS_INDEX - 1);
4658 for (attr = attrs[index]; attr; attr = attr->next)
4659 if (name == attr->name)
4660 return attr;
4661
4662 /* Otherwise, do it the slow way. */
4663 for (attr = attrs[index]; attr; attr = attr->next)
4664 if (name[0] == attr->name[0] && ! strcmp (s1: name, s2: attr->name))
4665 {
4666 *name_p = attr->name;
4667 return attr;
4668 }
4669
4670 if (! create)
4671 return NULL;
4672
4673 attr = oballoc (class attr_desc);
4674 attr->name = DEF_ATTR_STRING (name);
4675 attr->enum_name = 0;
4676 attr->first_value = attr->default_val = NULL;
4677 attr->is_numeric = attr->is_const = attr->is_special = 0;
4678 attr->next = attrs[index];
4679 attrs[index] = attr;
4680
4681 *name_p = attr->name;
4682
4683 return attr;
4684}
4685
4686/* Create internal attribute with the given default value. */
4687
4688static void
4689make_internal_attr (const char *name, rtx value, int special)
4690{
4691 class attr_desc *attr;
4692
4693 attr = find_attr (name_p: &name, create: 1);
4694 gcc_assert (!attr->default_val);
4695
4696 attr->is_numeric = 1;
4697 attr->is_const = 0;
4698 attr->is_special = (special & ATTR_SPECIAL) != 0;
4699 attr->default_val = get_attr_value (loc: file_location ("<internal>", 0, 0),
4700 value, attr, insn_code: -2);
4701}
4702
4703/* Find the most used value of an attribute. */
4704
4705static struct attr_value *
4706find_most_used (class attr_desc *attr)
4707{
4708 struct attr_value *av;
4709 struct attr_value *most_used;
4710 int nuses;
4711
4712 most_used = NULL;
4713 nuses = -1;
4714
4715 for (av = attr->first_value; av; av = av->next)
4716 if (av->num_insns > nuses)
4717 nuses = av->num_insns, most_used = av;
4718
4719 return most_used;
4720}
4721
4722/* Return (attr_value "n") */
4723
4724static rtx
4725make_numeric_value (int n)
4726{
4727 static rtx int_values[20];
4728 rtx exp;
4729 char *p;
4730
4731 gcc_assert (n >= 0);
4732
4733 if (n < 20 && int_values[n])
4734 return int_values[n];
4735
4736 p = attr_printf (MAX_DIGITS, fmt: "%d", n);
4737 exp = attr_rtx (code: CONST_STRING, p);
4738
4739 if (n < 20)
4740 int_values[n] = exp;
4741
4742 return exp;
4743}
4744
4745static rtx
4746copy_rtx_unchanging (rtx orig)
4747{
4748 if (ATTR_IND_SIMPLIFIED_P (orig) || ATTR_CURR_SIMPLIFIED_P (orig))
4749 return orig;
4750
4751 ATTR_CURR_SIMPLIFIED_P (orig) = 1;
4752 return orig;
4753}
4754
4755/* Determine if an insn has a constant number of delay slots, i.e., the
4756 number of delay slots is not a function of the length of the insn. */
4757
4758static void
4759write_const_num_delay_slots (FILE *outf)
4760{
4761 class attr_desc *attr = find_attr (name_p: &num_delay_slots_str, create: 0);
4762 struct attr_value *av;
4763
4764 if (attr)
4765 {
4766 fprintf (stream: outf, format: "int\nconst_num_delay_slots (rtx_insn *insn)\n");
4767 fprintf (stream: outf, format: "{\n");
4768 fprintf (stream: outf, format: " switch (recog_memoized (insn))\n");
4769 fprintf (stream: outf, format: " {\n");
4770
4771 for (av = attr->first_value; av; av = av->next)
4772 {
4773 length_used = 0;
4774 walk_attr_value (exp: av->value);
4775 if (length_used)
4776 write_insn_cases (outf, ie: av->first_insn, indent: 4);
4777 }
4778
4779 fprintf (stream: outf, format: " default:\n");
4780 fprintf (stream: outf, format: " return 1;\n");
4781 fprintf (stream: outf, format: " }\n}\n\n");
4782 }
4783}
4784
4785/* Synthetic attributes used by insn-automata.cc and the scheduler.
4786 These are primarily concerned with (define_insn_reservation)
4787 patterns. */
4788
4789struct insn_reserv
4790{
4791 struct insn_reserv *next;
4792
4793 const char *name;
4794 int default_latency;
4795 rtx condexp;
4796
4797 /* Sequence number of this insn. */
4798 int insn_num;
4799
4800 /* Whether a (define_bypass) construct names this insn in its
4801 output list. */
4802 bool bypassed;
4803};
4804
4805static struct insn_reserv *all_insn_reservs = 0;
4806static struct insn_reserv **last_insn_reserv_p = &all_insn_reservs;
4807static size_t n_insn_reservs;
4808
4809/* Store information from a DEFINE_INSN_RESERVATION for future
4810 attribute generation. */
4811static void
4812gen_insn_reserv (md_rtx_info *info)
4813{
4814 struct insn_reserv *decl = oballoc (struct insn_reserv);
4815 rtx def = info->def;
4816
4817 class attr_desc attr = { };
4818
4819 attr.name = DEF_ATTR_STRING (XSTR (def, 0));
4820 attr.loc = info->loc;
4821
4822 decl->name = DEF_ATTR_STRING (XSTR (def, 0));
4823 decl->default_latency = XINT (def, 1);
4824 decl->condexp = check_attr_test (loc: info->loc, XEXP (def, 2), attr: &attr);
4825 decl->insn_num = n_insn_reservs;
4826 decl->bypassed = false;
4827 decl->next = 0;
4828
4829 *last_insn_reserv_p = decl;
4830 last_insn_reserv_p = &decl->next;
4831 n_insn_reservs++;
4832}
4833
4834/* Store information from a DEFINE_BYPASS for future attribute
4835 generation. The only thing we care about is the list of output
4836 insns, which will later be used to tag reservation structures with
4837 a 'bypassed' bit. */
4838
4839struct bypass_list
4840{
4841 struct bypass_list *next;
4842 const char *pattern;
4843};
4844
4845static struct bypass_list *all_bypasses;
4846static size_t n_bypasses;
4847static size_t n_bypassed;
4848
4849static void
4850gen_bypass_1 (const char *s, size_t len)
4851{
4852 struct bypass_list *b;
4853
4854 if (len == 0)
4855 return;
4856
4857 s = attr_string (str: s, len);
4858 for (b = all_bypasses; b; b = b->next)
4859 if (s == b->pattern)
4860 return; /* already got that one */
4861
4862 b = oballoc (struct bypass_list);
4863 b->pattern = s;
4864 b->next = all_bypasses;
4865 all_bypasses = b;
4866 n_bypasses++;
4867}
4868
4869static void
4870gen_bypass (md_rtx_info *info)
4871{
4872 const char *p, *base;
4873
4874 rtx def = info->def;
4875 for (p = base = XSTR (def, 1); *p; p++)
4876 if (*p == ',')
4877 {
4878 gen_bypass_1 (s: base, len: p - base);
4879 do
4880 p++;
4881 while (ISSPACE (*p));
4882 base = p;
4883 }
4884 gen_bypass_1 (s: base, len: p - base);
4885}
4886
4887/* Find and mark all of the bypassed insns. */
4888static void
4889process_bypasses (void)
4890{
4891 struct bypass_list *b;
4892 struct insn_reserv *r;
4893
4894 n_bypassed = 0;
4895
4896 /* The reservation list is likely to be much longer than the bypass
4897 list. */
4898 for (r = all_insn_reservs; r; r = r->next)
4899 for (b = all_bypasses; b; b = b->next)
4900 if (fnmatch (pattern: b->pattern, string: r->name, flags: 0) == 0)
4901 {
4902 n_bypassed++;
4903 r->bypassed = true;
4904 break;
4905 }
4906}
4907
4908/* Check that attribute NAME is used in define_insn_reservation condition
4909 EXP. Return true if it is. */
4910static bool
4911check_tune_attr (const char *name, rtx exp)
4912{
4913 switch (GET_CODE (exp))
4914 {
4915 case AND:
4916 if (check_tune_attr (name, XEXP (exp, 0)))
4917 return true;
4918 return check_tune_attr (name, XEXP (exp, 1));
4919
4920 case IOR:
4921 return (check_tune_attr (name, XEXP (exp, 0))
4922 && check_tune_attr (name, XEXP (exp, 1)));
4923
4924 case EQ_ATTR:
4925 return XSTR (exp, 0) == name;
4926
4927 default:
4928 return false;
4929 }
4930}
4931
4932/* Try to find a const attribute (usually cpu or tune) that is used
4933 in all define_insn_reservation conditions. */
4934static class attr_desc *
4935find_tune_attr (rtx exp)
4936{
4937 class attr_desc *attr;
4938
4939 switch (GET_CODE (exp))
4940 {
4941 case AND:
4942 case IOR:
4943 attr = find_tune_attr (XEXP (exp, 0));
4944 if (attr)
4945 return attr;
4946 return find_tune_attr (XEXP (exp, 1));
4947
4948 case EQ_ATTR:
4949 if (XSTR (exp, 0) == alternative_name)
4950 return NULL;
4951
4952 attr = find_attr (name_p: &XSTR (exp, 0), create: 0);
4953 gcc_assert (attr);
4954
4955 if (attr->is_const && !attr->is_special)
4956 {
4957 struct insn_reserv *decl;
4958
4959 for (decl = all_insn_reservs; decl; decl = decl->next)
4960 if (! check_tune_attr (name: attr->name, exp: decl->condexp))
4961 return NULL;
4962 return attr;
4963 }
4964 return NULL;
4965
4966 default:
4967 return NULL;
4968 }
4969}
4970
4971/* Create all of the attributes that describe automaton properties.
4972 Write the DFA and latency function prototypes to the files that
4973 need to have them, and write the init_sched_attrs(). */
4974
4975static void
4976make_automaton_attrs (void)
4977{
4978 int i;
4979 struct insn_reserv *decl;
4980 rtx code_exp, lats_exp, byps_exp;
4981 class attr_desc *tune_attr;
4982
4983 if (n_insn_reservs == 0)
4984 return;
4985
4986 tune_attr = find_tune_attr (exp: all_insn_reservs->condexp);
4987 if (tune_attr != NULL)
4988 {
4989 rtx *condexps = XNEWVEC (rtx, n_insn_reservs * 3);
4990 struct attr_value *val;
4991 bool first = true;
4992
4993 gcc_assert (tune_attr->is_const
4994 && !tune_attr->is_special
4995 && !tune_attr->is_numeric);
4996
4997 /* Write the prototypes for all DFA functions. */
4998 for (val = tune_attr->first_value; val; val = val->next)
4999 {
5000 if (val == tune_attr->default_val)
5001 continue;
5002 gcc_assert (GET_CODE (val->value) == CONST_STRING);
5003 fprintf (stream: dfa_file,
5004 format: "extern int internal_dfa_insn_code_%s (rtx_insn *);\n",
5005 XSTR (val->value, 0));
5006 }
5007 fprintf (stream: dfa_file, format: "\n");
5008
5009 /* Write the prototypes for all latency functions. */
5010 for (val = tune_attr->first_value; val; val = val->next)
5011 {
5012 if (val == tune_attr->default_val)
5013 continue;
5014 gcc_assert (GET_CODE (val->value) == CONST_STRING);
5015 fprintf (stream: latency_file,
5016 format: "extern int insn_default_latency_%s (rtx_insn *);\n",
5017 XSTR (val->value, 0));
5018 }
5019 fprintf (stream: latency_file, format: "\n");
5020
5021 /* Write the prototypes for all automaton functions. */
5022 for (val = tune_attr->first_value; val; val = val->next)
5023 {
5024 if (val == tune_attr->default_val)
5025 continue;
5026 gcc_assert (GET_CODE (val->value) == CONST_STRING);
5027 fprintf (stream: attr_file,
5028 format: "extern int internal_dfa_insn_code_%s (rtx_insn *);\n"
5029 "extern int insn_default_latency_%s (rtx_insn *);\n",
5030 XSTR (val->value, 0), XSTR (val->value, 0));
5031 }
5032 fprintf (stream: attr_file, format: "\n");
5033 fprintf (stream: attr_file, format: "int (*internal_dfa_insn_code) (rtx_insn *);\n");
5034 fprintf (stream: attr_file, format: "int (*insn_default_latency) (rtx_insn *);\n");
5035 fprintf (stream: attr_file, format: "\n");
5036 fprintf (stream: attr_file, format: "void\n");
5037 fprintf (stream: attr_file, format: "init_sched_attrs (void)\n");
5038 fprintf (stream: attr_file, format: "{\n");
5039
5040 for (val = tune_attr->first_value; val; val = val->next)
5041 {
5042 int j;
5043 char *name;
5044 rtx test = attr_eq (name: tune_attr->name, XSTR (val->value, 0));
5045
5046 if (val == tune_attr->default_val)
5047 continue;
5048 for (decl = all_insn_reservs, i = 0;
5049 decl;
5050 decl = decl->next)
5051 {
5052 rtx ctest = test;
5053 rtx condexp
5054 = simplify_and_tree (exp: decl->condexp, pterm: &ctest, insn_code: -2, insn_index: 0);
5055 if (condexp == false_rtx)
5056 continue;
5057 if (condexp == true_rtx)
5058 break;
5059 condexps[i] = condexp;
5060 condexps[i + 1] = make_numeric_value (n: decl->insn_num);
5061 condexps[i + 2] = make_numeric_value (n: decl->default_latency);
5062 i += 3;
5063 }
5064
5065 code_exp = rtx_alloc (COND);
5066 lats_exp = rtx_alloc (COND);
5067
5068 j = i / 3 * 2;
5069 XVEC (code_exp, 0) = rtvec_alloc (j);
5070 XVEC (lats_exp, 0) = rtvec_alloc (j);
5071
5072 if (decl)
5073 {
5074 XEXP (code_exp, 1) = make_numeric_value (n: decl->insn_num);
5075 XEXP (lats_exp, 1) = make_numeric_value (n: decl->default_latency);
5076 }
5077 else
5078 {
5079 XEXP (code_exp, 1) = make_numeric_value (n: n_insn_reservs + 1);
5080 XEXP (lats_exp, 1) = make_numeric_value (n: 0);
5081 }
5082
5083 while (i > 0)
5084 {
5085 i -= 3;
5086 j -= 2;
5087 XVECEXP (code_exp, 0, j) = condexps[i];
5088 XVECEXP (lats_exp, 0, j) = condexps[i];
5089
5090 XVECEXP (code_exp, 0, j + 1) = condexps[i + 1];
5091 XVECEXP (lats_exp, 0, j + 1) = condexps[i + 2];
5092 }
5093
5094 name = XNEWVEC (char,
5095 sizeof ("*internal_dfa_insn_code_")
5096 + strlen (XSTR (val->value, 0)));
5097 strcpy (dest: name, src: "*internal_dfa_insn_code_");
5098 strcat (dest: name, XSTR (val->value, 0));
5099 make_internal_attr (name, value: code_exp, ATTR_NONE);
5100 strcpy (dest: name, src: "*insn_default_latency_");
5101 strcat (dest: name, XSTR (val->value, 0));
5102 make_internal_attr (name, value: lats_exp, ATTR_NONE);
5103 XDELETEVEC (name);
5104
5105 if (first)
5106 {
5107 fprintf (stream: attr_file, format: " if (");
5108 first = false;
5109 }
5110 else
5111 fprintf (stream: attr_file, format: " else if (");
5112 write_test_expr (outf: attr_file, exp: test, attrs_cached: 0, flags: 0);
5113 fprintf (stream: attr_file, format: ")\n");
5114 fprintf (stream: attr_file, format: " {\n");
5115 fprintf (stream: attr_file, format: " internal_dfa_insn_code\n");
5116 fprintf (stream: attr_file, format: " = internal_dfa_insn_code_%s;\n",
5117 XSTR (val->value, 0));
5118 fprintf (stream: attr_file, format: " insn_default_latency\n");
5119 fprintf (stream: attr_file, format: " = insn_default_latency_%s;\n",
5120 XSTR (val->value, 0));
5121 fprintf (stream: attr_file, format: " }\n");
5122 }
5123
5124 fprintf (stream: attr_file, format: " else\n");
5125 fprintf (stream: attr_file, format: " gcc_unreachable ();\n");
5126 fprintf (stream: attr_file, format: "}\n");
5127 fprintf (stream: attr_file, format: "\n");
5128
5129 XDELETEVEC (condexps);
5130 }
5131 else
5132 {
5133 code_exp = rtx_alloc (COND);
5134 lats_exp = rtx_alloc (COND);
5135
5136 XVEC (code_exp, 0) = rtvec_alloc (n_insn_reservs * 2);
5137 XVEC (lats_exp, 0) = rtvec_alloc (n_insn_reservs * 2);
5138
5139 XEXP (code_exp, 1) = make_numeric_value (n: n_insn_reservs + 1);
5140 XEXP (lats_exp, 1) = make_numeric_value (n: 0);
5141
5142 for (decl = all_insn_reservs, i = 0;
5143 decl;
5144 decl = decl->next, i += 2)
5145 {
5146 XVECEXP (code_exp, 0, i) = decl->condexp;
5147 XVECEXP (lats_exp, 0, i) = decl->condexp;
5148
5149 XVECEXP (code_exp, 0, i+1) = make_numeric_value (n: decl->insn_num);
5150 XVECEXP (lats_exp, 0, i+1)
5151 = make_numeric_value (n: decl->default_latency);
5152 }
5153 make_internal_attr (name: "*internal_dfa_insn_code", value: code_exp, ATTR_NONE);
5154 make_internal_attr (name: "*insn_default_latency", value: lats_exp, ATTR_NONE);
5155 }
5156
5157 if (n_bypasses == 0)
5158 byps_exp = make_numeric_value (n: 0);
5159 else
5160 {
5161 process_bypasses ();
5162
5163 byps_exp = rtx_alloc (COND);
5164 XVEC (byps_exp, 0) = rtvec_alloc (n_bypassed * 2);
5165 XEXP (byps_exp, 1) = make_numeric_value (n: 0);
5166 for (decl = all_insn_reservs, i = 0;
5167 decl;
5168 decl = decl->next)
5169 if (decl->bypassed)
5170 {
5171 XVECEXP (byps_exp, 0, i) = decl->condexp;
5172 XVECEXP (byps_exp, 0, i+1) = make_numeric_value (n: 1);
5173 i += 2;
5174 }
5175 }
5176
5177 make_internal_attr (name: "*bypass_p", value: byps_exp, ATTR_NONE);
5178}
5179
5180static void
5181write_header (FILE *outf)
5182{
5183 fprintf (stream: outf, format: "/* Generated automatically by the program `genattrtab'\n"
5184 " from the machine description file `md'. */\n\n");
5185
5186 fprintf (stream: outf, format: "#define IN_TARGET_CODE 1\n");
5187 fprintf (stream: outf, format: "#include \"config.h\"\n");
5188 fprintf (stream: outf, format: "#include \"system.h\"\n");
5189 fprintf (stream: outf, format: "#include \"coretypes.h\"\n");
5190 fprintf (stream: outf, format: "#include \"backend.h\"\n");
5191 fprintf (stream: outf, format: "#include \"predict.h\"\n");
5192 fprintf (stream: outf, format: "#include \"tree.h\"\n");
5193 fprintf (stream: outf, format: "#include \"rtl.h\"\n");
5194 fprintf (stream: outf, format: "#include \"alias.h\"\n");
5195 fprintf (stream: outf, format: "#include \"options.h\"\n");
5196 fprintf (stream: outf, format: "#include \"varasm.h\"\n");
5197 fprintf (stream: outf, format: "#include \"stor-layout.h\"\n");
5198 fprintf (stream: outf, format: "#include \"calls.h\"\n");
5199 fprintf (stream: outf, format: "#include \"insn-attr.h\"\n");
5200 fprintf (stream: outf, format: "#include \"memmodel.h\"\n");
5201 fprintf (stream: outf, format: "#include \"tm_p.h\"\n");
5202 fprintf (stream: outf, format: "#include \"insn-config.h\"\n");
5203 fprintf (stream: outf, format: "#include \"recog.h\"\n");
5204 fprintf (stream: outf, format: "#include \"regs.h\"\n");
5205 fprintf (stream: outf, format: "#include \"real.h\"\n");
5206 fprintf (stream: outf, format: "#include \"output.h\"\n");
5207 fprintf (stream: outf, format: "#include \"toplev.h\"\n");
5208 fprintf (stream: outf, format: "#include \"flags.h\"\n");
5209 fprintf (stream: outf, format: "#include \"emit-rtl.h\"\n");
5210 fprintf (stream: outf, format: "\n");
5211 fprintf (stream: outf, format: "#define operands recog_data.operand\n\n");
5212}
5213
5214static FILE *
5215open_outfile (const char *file_name)
5216{
5217 FILE *outf;
5218 outf = fopen (file_name, "w");
5219 if (! outf)
5220 fatal ("cannot open file %s: %s", file_name, xstrerror (errno));
5221 write_header (outf);
5222 return outf;
5223}
5224
5225static bool
5226handle_arg (const char *arg)
5227{
5228 switch (arg[1])
5229 {
5230 case 'A':
5231 attr_file_name = &arg[2];
5232 return true;
5233 case 'D':
5234 dfa_file_name = &arg[2];
5235 return true;
5236 case 'L':
5237 latency_file_name = &arg[2];
5238 return true;
5239 default:
5240 return false;
5241 }
5242}
5243
5244int
5245main (int argc, const char **argv)
5246{
5247 class attr_desc *attr;
5248 class insn_def *id;
5249 int i;
5250
5251 progname = "genattrtab";
5252
5253 if (!init_rtx_reader_args_cb (argc, argv, handle_arg))
5254 return FATAL_EXIT_CODE;
5255
5256 attr_file = open_outfile (file_name: attr_file_name);
5257 dfa_file = open_outfile (file_name: dfa_file_name);
5258 latency_file = open_outfile (file_name: latency_file_name);
5259
5260 obstack_init (hash_obstack);
5261 obstack_init (temp_obstack);
5262
5263 /* Set up true and false rtx's */
5264 true_rtx = rtx_alloc (CONST_INT);
5265 XWINT (true_rtx, 0) = 1;
5266 false_rtx = rtx_alloc (CONST_INT);
5267 XWINT (false_rtx, 0) = 0;
5268 ATTR_IND_SIMPLIFIED_P (true_rtx) = ATTR_IND_SIMPLIFIED_P (false_rtx) = 1;
5269 ATTR_PERMANENT_P (true_rtx) = ATTR_PERMANENT_P (false_rtx) = 1;
5270
5271 alternative_name = DEF_ATTR_STRING ("alternative");
5272 length_str = DEF_ATTR_STRING ("length");
5273 delay_type_str = DEF_ATTR_STRING ("*delay_type");
5274 delay_1_0_str = DEF_ATTR_STRING ("*delay_1_0");
5275 num_delay_slots_str = DEF_ATTR_STRING ("*num_delay_slots");
5276
5277 /* Read the machine description. */
5278
5279 md_rtx_info info;
5280 while (read_md_rtx (&info))
5281 {
5282 switch (GET_CODE (info.def))
5283 {
5284 case DEFINE_INSN:
5285 case DEFINE_PEEPHOLE:
5286 case DEFINE_ASM_ATTRIBUTES:
5287 gen_insn (info: &info);
5288 break;
5289
5290 case DEFINE_ATTR:
5291 case DEFINE_ENUM_ATTR:
5292 gen_attr (info: &info);
5293 break;
5294
5295 case DEFINE_DELAY:
5296 gen_delay (info: &info);
5297 break;
5298
5299 case DEFINE_INSN_RESERVATION:
5300 gen_insn_reserv (info: &info);
5301 break;
5302
5303 case DEFINE_BYPASS:
5304 gen_bypass (info: &info);
5305 break;
5306
5307 default:
5308 break;
5309 }
5310 if (GET_CODE (info.def) != DEFINE_ASM_ATTRIBUTES)
5311 insn_index_number++;
5312 }
5313
5314 if (have_error)
5315 return FATAL_EXIT_CODE;
5316
5317 /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one. */
5318 if (! got_define_asm_attributes)
5319 {
5320 md_rtx_info info;
5321 info.def = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
5322 XVEC (info.def, 0) = rtvec_alloc (0);
5323 info.loc = file_location ("<internal>", 0, 0);
5324 info.index = -1;
5325 gen_insn (info: &info);
5326 }
5327
5328 /* Expand DEFINE_DELAY information into new attribute. */
5329 expand_delays ();
5330
5331 /* Make `insn_alternatives'. */
5332 int num_insn_codes = get_num_insn_codes ();
5333 insn_alternatives = oballocvec (alternative_mask, num_insn_codes);
5334 for (id = defs; id; id = id->next)
5335 if (id->insn_code >= 0)
5336 insn_alternatives[id->insn_code]
5337 = (((alternative_mask) 1) << id->num_alternatives) - 1;
5338
5339 /* Make `insn_n_alternatives'. */
5340 insn_n_alternatives = oballocvec (int, num_insn_codes);
5341 for (id = defs; id; id = id->next)
5342 if (id->insn_code >= 0)
5343 insn_n_alternatives[id->insn_code] = id->num_alternatives;
5344
5345 /* Construct extra attributes for automata. */
5346 make_automaton_attrs ();
5347
5348 /* Prepare to write out attribute subroutines by checking everything stored
5349 away and building the attribute cases. */
5350
5351 check_defs ();
5352
5353 for (i = 0; i < MAX_ATTRS_INDEX; i++)
5354 for (attr = attrs[i]; attr; attr = attr->next)
5355 attr->default_val->value
5356 = check_attr_value (loc: attr->loc, exp: attr->default_val->value, attr);
5357
5358 if (have_error)
5359 return FATAL_EXIT_CODE;
5360
5361 for (i = 0; i < MAX_ATTRS_INDEX; i++)
5362 for (attr = attrs[i]; attr; attr = attr->next)
5363 fill_attr (attr);
5364
5365 /* Construct extra attributes for `length'. */
5366 make_length_attrs ();
5367
5368 /* Perform any possible optimizations to speed up compilation. */
5369 optimize_attrs (num_insn_codes);
5370
5371 /* Now write out all the `gen_attr_...' routines. Do these before the
5372 special routines so that they get defined before they are used. */
5373
5374 for (i = 0; i < MAX_ATTRS_INDEX; i++)
5375 for (attr = attrs[i]; attr; attr = attr->next)
5376 {
5377 FILE *outf;
5378
5379 if (startswith(str: attr->name, prefix: "*internal_dfa_insn_code"))
5380 outf = dfa_file;
5381 else if (startswith (str: attr->name, prefix: "*insn_default_latency"))
5382 outf = latency_file;
5383 else
5384 outf = attr_file;
5385
5386 if (! attr->is_special && ! attr->is_const)
5387 write_attr_get (outf, attr);
5388 }
5389
5390 /* Write out delay eligibility information, if DEFINE_DELAY present.
5391 (The function to compute the number of delay slots will be written
5392 below.) */
5393 write_eligible_delay (outf: attr_file, kind: "delay");
5394 if (have_annul_true)
5395 write_eligible_delay (outf: attr_file, kind: "annul_true");
5396 else
5397 write_dummy_eligible_delay (outf: attr_file, kind: "annul_true");
5398 if (have_annul_false)
5399 write_eligible_delay (outf: attr_file, kind: "annul_false");
5400 else
5401 write_dummy_eligible_delay (outf: attr_file, kind: "annul_false");
5402
5403 /* Write out constant delay slot info. */
5404 write_const_num_delay_slots (outf: attr_file);
5405
5406 write_length_unit_log (outf: attr_file);
5407
5408 if (fclose (stream: attr_file) != 0)
5409 fatal ("cannot close file %s: %s", attr_file_name, xstrerror (errno));
5410 if (fclose (stream: dfa_file) != 0)
5411 fatal ("cannot close file %s: %s", dfa_file_name, xstrerror (errno));
5412 if (fclose (stream: latency_file) != 0)
5413 fatal ("cannot close file %s: %s", latency_file_name, xstrerror (errno));
5414
5415 return SUCCESS_EXIT_CODE;
5416}
5417
5418

source code of gcc/genattrtab.cc