|
|
1.1 root 1: /* Generate code from machine description to compute values of attributes.
2: Copyright (C) 1991 Free Software Foundation, Inc.
3: Contributed by Richard Kenner ([email protected])
4:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
1.1.1.3 ! root 21: /* This program handles insn attributes and the DEFINE_DELAY and
1.1 root 22: DEFINE_FUNCTION_UNIT definitions.
23:
1.1.1.2 root 24: It produces a series of functions named `get_attr_...', one for each insn
1.1 root 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, `insn_extract' 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:
1.1.1.2 root 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:
1.1 root 54: Internal attributes are defined to handle DEFINE_DELAY and
55: DEFINE_FUNCTION_UNIT. 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 and DEFINE_FUNCTION_UNIT
72: definitions is to create arbitrarily complex expressions and have the
73: optimization simplify them.
74:
75: Once optimization is complete, any required routines and definitions
1.1.1.2 root 76: will be written.
77:
78: An optimization that is not yet implemented is to hoist the constant
79: expressions entirely out of the routines and definitions that are written.
80: A way to do this is to iterate over all possible combinations of values
81: for constant attributes and generate a set of functions for that given
82: combination. An initialization function would be written that evaluates
83: the attributes and installs the corresponding set of routines and
1.1.1.3 ! root 84: definitions (each would be accessed through a pointer).
! 85:
! 86: We use the flags in an RTX as follows:
! 87: `unchanging' (RTX_UNCHANGING_P): This rtx is fully simplified
! 88: independent of the insn code.
! 89: `in_struct' (MEM_IN_STRUCT_P): This rtx is fully simplified
! 90: for the insn code currently being processed (see optimize_attrs).
! 91: `integrated' (RTX_INTEGRATED_P): This rtx is permanent and unique
! 92: (see attr_rtx). */
! 93:
1.1 root 94:
95: #include <stdio.h>
1.1.1.2 root 96: #include "gvarargs.h"
1.1 root 97: #include "config.h"
98: #include "rtl.h"
99: #include "obstack.h"
100: #include "insn-config.h" /* For REGISTER_CONSTRAINTS */
101:
1.1.1.3 ! root 102: static struct obstack obstack, obstack1, obstack2;
1.1 root 103: struct obstack *rtl_obstack = &obstack;
1.1.1.3 ! root 104: struct obstack *hash_obstack = &obstack1;
! 105: struct obstack *temp_obstack = &obstack2;
1.1 root 106:
107: #define obstack_chunk_alloc xmalloc
108: #define obstack_chunk_free free
109:
1.1.1.3 ! root 110: /* Define this so we can link with print-rtl.o to get debug_rtx function. */
! 111: char **insn_name_ptr = 0;
! 112:
1.1 root 113: extern void free ();
1.1.1.3 ! root 114: extern rtx read_rtx ();
1.1 root 115:
116: static void fatal ();
117: void fancy_abort ();
118:
119: /* Define structures used to record attributes and values. */
120:
121: /* As each DEFINE_INSN, DEFINE_PEEPHOLE, or DEFINE_ASM_ATTRIBUTES is
122: encountered, we store all the relevant information into a
123: `struct insn_def'. This is done to allow attribute definitions to occur
124: anywhere in the file. */
125:
126: struct insn_def
127: {
128: int insn_code; /* Instruction number. */
129: int insn_index; /* Expression numer in file, for errors. */
130: struct insn_def *next; /* Next insn in chain. */
131: rtx def; /* The DEFINE_... */
132: int num_alternatives; /* Number of alternatives. */
133: int vec_idx; /* Index of attribute vector in `def'. */
134: };
135:
136: /* Once everything has been read in, we store in each attribute value a list
137: of insn codes that have that value. Here is the structure used for the
138: list. */
139:
140: struct insn_ent
141: {
142: int insn_code; /* Instruction number. */
143: int insn_index; /* Index of definition in file */
144: struct insn_ent *next; /* Next in chain. */
145: };
146:
147: /* Each value of an attribute (either constant or computed) is assigned a
148: structure which is used as the listhead of the insns that have that
149: value. */
150:
151: struct attr_value
152: {
153: rtx value; /* Value of attribute. */
154: struct attr_value *next; /* Next attribute value in chain. */
155: struct insn_ent *first_insn; /* First insn with this value. */
156: int num_insns; /* Number of insns with this value. */
157: int has_asm_insn; /* True if this value used for `asm' insns */
158: };
159:
160: /* Structure for each attribute. */
161:
162: struct attr_desc
163: {
164: char *name; /* Name of attribute. */
165: struct attr_desc *next; /* Next attribute. */
166: int is_numeric; /* Values of this attribute are numeric. */
1.1.1.2 root 167: int is_const; /* Attribute value constant for each run. */
1.1 root 168: int is_special; /* Don't call `write_attr_set'. */
169: struct attr_value *first_value; /* First value of this attribute. */
170: struct attr_value *default_val; /* Default value for this attribute. */
171: };
172:
173: /* Structure for each DEFINE_DELAY. */
174:
175: struct delay_desc
176: {
177: rtx def; /* DEFINE_DELAY expression. */
178: struct delay_desc *next; /* Next DEFINE_DELAY. */
179: int num; /* Number of DEFINE_DELAY, starting at 1. */
180: };
181:
182: /* Record information about each DEFINE_FUNCTION_UNIT. */
183:
184: struct function_unit_op
185: {
186: rtx condexp; /* Expression TRUE for applicable insn. */
187: struct function_unit_op *next; /* Next operation for this function unit. */
188: int num; /* Ordinal for this operation type in unit. */
189: int ready; /* Cost until data is ready. */
190: rtx busyexp; /* Expression computing conflict cost. */
191: };
192:
193: /* Record information about each function unit mentioned in a
194: DEFINE_FUNCTION_UNIT. */
195:
196: struct function_unit
197: {
198: char *name; /* Function unit name. */
199: struct function_unit *next; /* Next function unit. */
200: int num; /* Ordinal of this unit type. */
201: int multiplicity; /* Number of units of this type. */
202: int simultaneity; /* Maximum number of simultaneous insns
203: on this function unit or 0 if unlimited. */
204: rtx condexp; /* Expression TRUE for insn needing unit. */
205: rtx costexp; /* Worst-case cost as function of insn. */
206: int num_opclasses; /* Number of different operation types. */
207: struct function_unit_op *ops; /* Pointer to first operation type. */
208: int needs_conflict_function; /* Nonzero if a conflict function required. */
209: rtx default_cost; /* Conflict cost, if constant. */
210: };
211:
212: /* Listheads of above structures. */
213:
1.1.1.3 ! root 214: /* This one is indexed by the first character of the attribute name. */
! 215: #define MAX_ATTRS_INDEX 256
! 216: static struct attr_desc *attrs[MAX_ATTRS_INDEX];
1.1 root 217: static struct insn_def *defs;
218: static struct delay_desc *delays;
219: static struct function_unit *units;
220:
221: /* Other variables. */
222:
223: static int insn_code_number;
224: static int insn_index_number;
225: static int got_define_asm_attributes;
226: static int must_extract;
227: static int must_constrain;
228: static int address_used;
229: static int num_delays;
230: static int have_annul_true, have_annul_false;
231: static int num_units;
232:
233: /* Used as operand to `operate_exp': */
234:
235: enum operator {PLUS_OP, MINUS_OP, OR_OP, MAX_OP};
236:
1.1.1.3 ! root 237: /* Stores, for each insn code, the number of constraint alternatives. */
! 238:
! 239: static int *insn_n_alternatives;
! 240:
1.1 root 241: /* Stores, for each insn code, a bitmap that has bits on for each possible
242: alternative. */
243:
244: static int *insn_alternatives;
245:
1.1.1.3 ! root 246: /* If nonzero, assume that the `alternative' attr has this value.
! 247: This is the hashed, unique string for the numeral
! 248: whose value is chosen alternative. */
! 249:
! 250: static char *current_alternative_string;
! 251:
1.1 root 252: /* Used to simplify expressions. */
253:
254: static rtx true_rtx, false_rtx;
255:
256: /* Used to reduce calls to `strcmp' */
257:
1.1.1.3 ! root 258: static char *alternative_name;
1.1 root 259:
260: /* Simplify an expression. Only call the routine if there is something to
261: simplify. */
262: #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \
1.1.1.3 ! root 263: (RTX_UNCHANGING_P (EXP) || MEM_IN_STRUCT_P (EXP) ? (EXP) \
1.1 root 264: : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX))
265:
1.1.1.3 ! root 266: /* Simplify (eq_attr ("alternative") ...)
! 267: when we are working with a particular alternative. */
! 268: #define SIMPLIFY_ALTERNATIVE(EXP) \
! 269: if (current_alternative_string \
! 270: && GET_CODE ((EXP)) == EQ_ATTR \
! 271: && XSTR ((EXP), 0) == alternative_name) \
! 272: (EXP) = (XSTR ((EXP), 1) == current_alternative_string \
! 273: ? true_rtx : false_rtx);
! 274:
1.1 root 275: /* These are referenced by rtlanal.c and hence need to be defined somewhere.
276: They won't actually be used. */
277:
278: rtx frame_pointer_rtx, stack_pointer_rtx, arg_pointer_rtx;
279:
1.1.1.2 root 280: static rtx attr_rtx ();
281: static char *attr_printf ();
282: static char *attr_string ();
1.1 root 283: static rtx check_attr_test ();
1.1.1.3 ! root 284: static rtx check_attr_value ();
1.1 root 285: static rtx convert_set_attr_alternative ();
286: static rtx convert_set_attr ();
287: static void check_defs ();
1.1.1.2 root 288: static rtx convert_const_symbol_ref ();
1.1 root 289: static rtx make_canonical ();
290: static struct attr_value *get_attr_value ();
1.1.1.3 ! root 291: static rtx copy_rtx_unchanging ();
! 292: static rtx copy_boolean ();
1.1 root 293: static void expand_delays ();
294: static rtx operate_exp ();
295: static void expand_units ();
296: static void fill_attr ();
297: static rtx substitute_address ();
298: static void make_length_attrs ();
299: static rtx identity_fn ();
300: static rtx zero_fn ();
301: static rtx one_fn ();
302: static rtx max_fn ();
303: static rtx simplify_cond ();
1.1.1.3 ! root 304: static rtx simplify_by_alternatives ();
1.1 root 305: static void remove_insn_ent ();
306: static void insert_insn_ent ();
307: static rtx insert_right_side ();
308: static rtx make_alternative_compare ();
309: static int compute_alternative_mask ();
310: static rtx evaluate_eq_attr ();
311: static rtx simplify_and_tree ();
312: static rtx simplify_or_tree ();
313: static rtx simplify_test_exp ();
314: static void optimize_attrs ();
315: static void gen_attr ();
316: static int count_alternatives ();
317: static int compares_alternatives_p ();
318: static int contained_in_p ();
319: static void gen_insn ();
320: static void gen_delay ();
321: static void gen_unit ();
322: static void write_test_expr ();
323: static int max_attr_value ();
324: static void walk_attr_value ();
325: static void write_attr_get ();
326: static rtx eliminate_known_true ();
327: static void write_attr_set ();
328: static void write_attr_case ();
329: static void write_attr_value ();
330: static void write_attr_valueq ();
331: static void write_upcase ();
332: static void write_indent ();
333: static void write_eligible_delay ();
334: static void write_function_unit_info ();
335: static int n_comma_elts ();
336: static char *next_comma_elt ();
337: static struct attr_desc *find_attr ();
338: static void make_internal_attr ();
339: static struct attr_value *find_most_used ();
340: static rtx find_single_value ();
341: static rtx make_numeric_value ();
342: char *xrealloc ();
343: char *xmalloc ();
344: static void fatal ();
345:
1.1.1.2 root 346: /* Hash table for sharing RTL and strings. */
347:
348: /* Each hash table slot is a bucket containing a chain of these structures.
349: Strings are given negative hash codes; RTL expressions are given positive
350: hash codes. */
351:
352: struct attr_hash
353: {
354: struct attr_hash *next; /* Next structure in the bucket. */
355: int hashcode; /* Hash code of this rtx or string. */
356: union
357: {
358: char *str; /* The string (negative hash codes) */
359: rtx rtl; /* or the RTL recorded here. */
360: } u;
361: };
362:
363: /* Now here is the hash table. When recording an RTL, it is added to
364: the slot whose index is the hash code mod the table size. Note
365: that the hash table is used for several kinds of RTL (see attr_rtx)
366: and for strings. While all these live in the same table, they are
367: completely independent, and the hash code is computed differently
368: for each. */
369:
370: #define RTL_HASH_SIZE 4093
371: struct attr_hash *attr_hash_table[RTL_HASH_SIZE];
372:
373: /* Here is how primitive or already-shared RTL's hash
374: codes are made. */
375: #define RTL_HASH(RTL) ((int) (RTL) & 0777777)
376:
377: /* Add an entry to the hash table for RTL with hash code HASHCODE. */
378:
379: static void
380: attr_hash_add_rtx (hashcode, rtl)
381: int hashcode;
382: rtx rtl;
383: {
384: register struct attr_hash *h;
385:
1.1.1.3 ! root 386: h = (struct attr_hash *) obstack_alloc (hash_obstack,
! 387: sizeof (struct attr_hash));
1.1.1.2 root 388: h->hashcode = hashcode;
389: h->u.rtl = rtl;
390: h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
391: attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
392: }
393:
394: /* Add an entry to the hash table for STRING with hash code HASHCODE. */
395:
396: static void
397: attr_hash_add_string (hashcode, str)
398: int hashcode;
399: char *str;
400: {
401: register struct attr_hash *h;
402:
1.1.1.3 ! root 403: h = (struct attr_hash *) obstack_alloc (hash_obstack,
! 404: sizeof (struct attr_hash));
1.1.1.2 root 405: h->hashcode = -hashcode;
406: h->u.str = str;
407: h->next = attr_hash_table[hashcode % RTL_HASH_SIZE];
408: attr_hash_table[hashcode % RTL_HASH_SIZE] = h;
409: }
410:
1.1.1.3 ! root 411: /* Generate an RTL expression, but avoid duplicates.
! 412: Set the RTX_INTEGRATED_P flag for these permanent objects.
! 413:
! 414: In some cases we cannot uniquify; then we return an ordinary
! 415: impermanent rtx with RTX_INTEGRATED_P clear.
! 416:
! 417: Args are like gen_rtx, but without the mode:
1.1.1.2 root 418:
419: rtx attr_rtx (code, [element1, ..., elementn]) */
420:
421: /*VARARGS1*/
422: static rtx
423: attr_rtx (va_alist)
424: va_dcl
425: {
426: va_list p;
427: enum rtx_code code;
428: register int i; /* Array indices... */
429: register char *fmt; /* Current rtx's format... */
430: register rtx rt_val; /* RTX to return to caller... */
431: int hashcode;
432: register struct attr_hash *h;
1.1.1.3 ! root 433: struct obstack *old_obstack = rtl_obstack;
1.1.1.2 root 434:
435: va_start (p);
436: code = va_arg (p, enum rtx_code);
437:
438: /* For each of several cases, search the hash table for an existing entry.
439: Use that entry if one is found; otherwise create a new RTL and add it
440: to the table. */
441:
442: if (GET_RTX_CLASS (code) == '1')
443: {
444: rtx arg0 = va_arg (p, rtx);
445:
1.1.1.3 ! root 446: /* A permanent object cannot point to impermanent ones. */
! 447: if (! RTX_INTEGRATED_P (arg0))
! 448: {
! 449: rt_val = rtx_alloc (code);
! 450: XEXP (rt_val, 0) = arg0;
! 451: va_end (p);
! 452: return rt_val;
! 453: }
! 454:
! 455: hashcode = ((int) code + RTL_HASH (arg0));
1.1.1.2 root 456: for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
457: if (h->hashcode == hashcode
458: && GET_CODE (h->u.rtl) == code
459: && XEXP (h->u.rtl, 0) == arg0)
460: goto found;
461:
462: if (h == 0)
463: {
1.1.1.3 ! root 464: rtl_obstack = hash_obstack;
1.1.1.2 root 465: rt_val = rtx_alloc (code);
466: XEXP (rt_val, 0) = arg0;
467: }
468: }
469: else if (GET_RTX_CLASS (code) == 'c'
470: || GET_RTX_CLASS (code) == '2'
471: || GET_RTX_CLASS (code) == '<')
472: {
473: rtx arg0 = va_arg (p, rtx);
474: rtx arg1 = va_arg (p, rtx);
475:
1.1.1.3 ! root 476: /* A permanent object cannot point to impermanent ones. */
! 477: if (! RTX_INTEGRATED_P (arg0) || ! RTX_INTEGRATED_P (arg1))
! 478: {
! 479: rt_val = rtx_alloc (code);
! 480: XEXP (rt_val, 0) = arg0;
! 481: XEXP (rt_val, 1) = arg1;
! 482: va_end (p);
! 483: return rt_val;
! 484: }
! 485:
! 486: hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1));
1.1.1.2 root 487: for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
488: if (h->hashcode == hashcode
489: && GET_CODE (h->u.rtl) == code
490: && XEXP (h->u.rtl, 0) == arg0
491: && XEXP (h->u.rtl, 1) == arg1)
492: goto found;
493:
494: if (h == 0)
495: {
1.1.1.3 ! root 496: rtl_obstack = hash_obstack;
1.1.1.2 root 497: rt_val = rtx_alloc (code);
498: XEXP (rt_val, 0) = arg0;
499: XEXP (rt_val, 1) = arg1;
500: }
501: }
502: else if (GET_RTX_LENGTH (code) == 1
503: && GET_RTX_FORMAT (code)[0] == 's')
504: {
505: char * arg0 = va_arg (p, char *);
506:
1.1.1.3 ! root 507: if (code == SYMBOL_REF)
! 508: arg0 = attr_string (arg0, strlen (arg0));
! 509:
! 510: hashcode = ((int) code + RTL_HASH (arg0));
1.1.1.2 root 511: for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
512: if (h->hashcode == hashcode
513: && GET_CODE (h->u.rtl) == code
514: && XSTR (h->u.rtl, 0) == arg0)
515: goto found;
516:
517: if (h == 0)
518: {
1.1.1.3 ! root 519: rtl_obstack = hash_obstack;
1.1.1.2 root 520: rt_val = rtx_alloc (code);
521: XSTR (rt_val, 0) = arg0;
522: }
523: }
524: else if (GET_RTX_LENGTH (code) == 2
525: && GET_RTX_FORMAT (code)[0] == 's'
526: && GET_RTX_FORMAT (code)[1] == 's')
527: {
1.1.1.3 ! root 528: char *arg0 = va_arg (p, char *);
! 529: char *arg1 = va_arg (p, char *);
1.1.1.2 root 530:
1.1.1.3 ! root 531: hashcode = ((int) code + RTL_HASH (arg0) + RTL_HASH (arg1));
1.1.1.2 root 532: for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
533: if (h->hashcode == hashcode
534: && GET_CODE (h->u.rtl) == code
535: && XSTR (h->u.rtl, 0) == arg0
536: && XSTR (h->u.rtl, 1) == arg1)
537: goto found;
538:
539: if (h == 0)
540: {
1.1.1.3 ! root 541: rtl_obstack = hash_obstack;
1.1.1.2 root 542: rt_val = rtx_alloc (code);
543: XSTR (rt_val, 0) = arg0;
544: XSTR (rt_val, 1) = arg1;
545: }
546: }
1.1.1.3 ! root 547: else if (code == CONST_INT)
! 548: {
! 549: int arg0 = va_arg (p, int);
! 550: if (arg0 == 0)
! 551: return false_rtx;
! 552: if (arg0 == 1)
! 553: return true_rtx;
! 554: goto nohash;
! 555: }
1.1.1.2 root 556: else
557: {
1.1.1.3 ! root 558: nohash:
1.1.1.2 root 559: rt_val = rtx_alloc (code); /* Allocate the storage space. */
560:
561: fmt = GET_RTX_FORMAT (code); /* Find the right format... */
562: for (i = 0; i < GET_RTX_LENGTH (code); i++)
563: {
564: switch (*fmt++)
565: {
566: case '0': /* Unused field. */
567: break;
568:
569: case 'i': /* An integer? */
570: XINT (rt_val, i) = va_arg (p, int);
571: break;
572:
573: case 's': /* A string? */
574: XSTR (rt_val, i) = va_arg (p, char *);
575: break;
576:
577: case 'e': /* An expression? */
578: case 'u': /* An insn? Same except when printing. */
579: XEXP (rt_val, i) = va_arg (p, rtx);
580: break;
581:
582: case 'E': /* An RTX vector? */
583: XVEC (rt_val, i) = va_arg (p, rtvec);
584: break;
585:
586: default:
587: abort();
588: }
589: }
590: va_end (p);
591: return rt_val;
592: }
593:
1.1.1.3 ! root 594: rtl_obstack = old_obstack;
1.1.1.2 root 595: va_end (p);
596: attr_hash_add_rtx (hashcode, rt_val);
1.1.1.3 ! root 597: RTX_INTEGRATED_P (rt_val) = 1;
1.1.1.2 root 598: return rt_val;
599:
600: found:
601: va_end (p);
602: return h->u.rtl;
603: }
604:
605: /* Create a new string printed with the printf line arguments into a space
606: of at most LEN bytes:
607:
608: rtx attr_printf (len, format, [arg1, ..., argn]) */
609:
610: #ifdef HAVE_VPRINTF
611:
612: /*VARARGS2*/
613: static char *
614: attr_printf (va_alist)
615: va_dcl
616: {
617: va_list p;
618: register int len;
619: register char *fmt;
620: register char *str;
621:
622: /* Print the string into a temporary location. */
623: va_start (p);
624: len = va_arg (p, int);
625: str = (char *) alloca (len);
626: fmt = va_arg (p, char *);
627: vsprintf (str, fmt, p);
628: va_end (p);
629:
630: return attr_string (str, strlen (str));
631: }
632:
633: #else /* not HAVE_VPRINTF */
634:
635: static char *
636: attr_printf (len, fmt, arg1, arg2, arg3)
637: int len;
638: char *fmt;
639: char *arg1, *arg2, *arg3; /* also int */
640: {
641: register char *str;
642:
643: /* Print the string into a temporary location. */
644: str = (char *) alloca (len);
645: sprintf (str, fmt, arg1, arg2, arg3);
646:
647: return attr_string (str, strlen (str));
648: }
649: #endif /* not HAVE_VPRINTF */
650:
1.1.1.3 ! root 651: rtx
! 652: attr_eq (name, value)
! 653: char *name, *value;
! 654: {
! 655: return attr_rtx (EQ_ATTR, attr_string (name, strlen (name)),
! 656: attr_string (value, strlen (value)));
! 657: }
! 658:
! 659: char *
! 660: attr_numeral (n)
! 661: int n;
! 662: {
! 663: return XSTR (make_numeric_value (n), 0);
! 664: }
! 665:
1.1.1.2 root 666: /* Return a permanent (possibly shared) copy of a string STR (not assumed
667: to be null terminated) with LEN bytes. */
668:
669: static char *
670: attr_string (str, len)
671: char *str;
672: int len;
673: {
674: register struct attr_hash *h;
675: int hashcode;
676: int i;
677: register char *new_str;
678:
679: /* Compute the hash code. */
680: hashcode = (len + 1) * 613 + (unsigned)str[0];
681: for (i = 1; i <= len; i += 2)
682: hashcode = ((hashcode * 613) + (unsigned)str[i]);
683: if (hashcode < 0)
684: hashcode = -hashcode;
685:
686: /* Search the table for the string. */
687: for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
1.1.1.3 ! root 688: if (h->hashcode == -hashcode && h->u.str[0] == str[0]
1.1.1.2 root 689: && !strncmp (h->u.str, str, len))
690: return h->u.str; /* <-- return if found. */
691:
692: /* Not found; create a permanent copy and add it to the hash table. */
1.1.1.3 ! root 693: new_str = (char *) obstack_alloc (hash_obstack, len + 1);
1.1.1.2 root 694: bcopy (str, new_str, len);
695: new_str[len] = '\0';
696: attr_hash_add_string (hashcode, new_str);
697:
698: return new_str; /* Return the new string. */
699: }
1.1.1.3 ! root 700:
! 701: /* Check two rtx's for equality of contents,
! 702: taking advantage of the fact that if both are hashed
! 703: then they can't be equal unless they are the same object. */
! 704:
! 705: int
! 706: attr_equal_p (x, y)
! 707: rtx x, y;
! 708: {
! 709: return (x == y || (! (RTX_INTEGRATED_P (x) && RTX_INTEGRATED_P (y))
! 710: && rtx_equal_p (x, y)));
! 711: }
! 712:
! 713: /* Copy an attribute value expression,
! 714: descending to all depths, but not copying any
! 715: permanent hashed subexpressions. */
! 716:
! 717: rtx
! 718: attr_copy_rtx (orig)
! 719: register rtx orig;
! 720: {
! 721: register rtx copy;
! 722: register int i, j;
! 723: register RTX_CODE code;
! 724: register char *format_ptr;
! 725:
! 726: /* No need to copy a permanent object. */
! 727: if (RTX_INTEGRATED_P (orig))
! 728: return orig;
! 729:
! 730: code = GET_CODE (orig);
! 731:
! 732: switch (code)
! 733: {
! 734: case REG:
! 735: case QUEUED:
! 736: case CONST_INT:
! 737: case CONST_DOUBLE:
! 738: case SYMBOL_REF:
! 739: case CODE_LABEL:
! 740: case PC:
! 741: case CC0:
! 742: return orig;
! 743: }
! 744:
! 745: copy = rtx_alloc (code);
! 746: PUT_MODE (copy, GET_MODE (orig));
! 747: copy->in_struct = orig->in_struct;
! 748: copy->volatil = orig->volatil;
! 749: copy->unchanging = orig->unchanging;
! 750: copy->integrated = orig->integrated;
! 751:
! 752: format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
! 753:
! 754: for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
! 755: {
! 756: switch (*format_ptr++)
! 757: {
! 758: case 'e':
! 759: XEXP (copy, i) = XEXP (orig, i);
! 760: if (XEXP (orig, i) != NULL)
! 761: XEXP (copy, i) = attr_copy_rtx (XEXP (orig, i));
! 762: break;
! 763:
! 764: case 'E':
! 765: case 'V':
! 766: XVEC (copy, i) = XVEC (orig, i);
! 767: if (XVEC (orig, i) != NULL)
! 768: {
! 769: XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
! 770: for (j = 0; j < XVECLEN (copy, i); j++)
! 771: XVECEXP (copy, i, j) = attr_copy_rtx (XVECEXP (orig, i, j));
! 772: }
! 773: break;
! 774:
! 775: default:
! 776: XINT (copy, i) = XINT (orig, i);
! 777: break;
! 778: }
! 779: }
! 780: return copy;
! 781: }
1.1.1.2 root 782:
1.1 root 783: /* Given a test expression for an attribute, ensure it is validly formed.
1.1.1.2 root 784: IS_CONST indicates whether the expression is constant for each compiler
785: run (a constant expression may not test any particular insn).
786:
1.1 root 787: Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..))
788: and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")). Do the latter
789: test first so that (eq_attr "att" "!a1,a2,a3") works as expected.
790:
791: Update the string address in EQ_ATTR expression to be the same used
792: in the attribute (or `alternative_name') to speed up subsequent
793: `find_attr' calls and eliminate most `strcmp' calls.
794:
795: Return the new expression, if any. */
796:
797: static rtx
1.1.1.2 root 798: check_attr_test (exp, is_const)
1.1 root 799: rtx exp;
1.1.1.2 root 800: int is_const;
1.1 root 801: {
802: struct attr_desc *attr;
803: struct attr_value *av;
804: char *name_ptr, *p;
805: rtx orexp, newexp;
806:
807: switch (GET_CODE (exp))
808: {
809: case EQ_ATTR:
810: /* Handle negation test. */
811: if (XSTR (exp, 1)[0] == '!')
1.1.1.2 root 812: return check_attr_test (attr_rtx (NOT,
1.1.1.3 ! root 813: attr_eq (XSTR (exp, 0),
! 814: &XSTR (exp, 1)[1])),
1.1.1.2 root 815: is_const);
1.1 root 816:
817: else if (n_comma_elts (XSTR (exp, 1)) == 1)
818: {
1.1.1.3 ! root 819: attr = find_attr (XSTR (exp, 0), 0);
1.1 root 820: if (attr == NULL)
821: {
822: if (! strcmp (XSTR (exp, 0), "alternative"))
823: {
824: XSTR (exp, 0) = alternative_name;
825: /* This can't be simplified any further. */
826: RTX_UNCHANGING_P (exp) = 1;
827: return exp;
828: }
1.1.1.3 ! root 829: else
1.1 root 830: fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0));
831: }
832:
1.1.1.2 root 833: if (is_const && ! attr->is_const)
834: fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR",
835: XEXP (exp, 0));
836:
1.1.1.3 ! root 837: /* Copy this just to make it permanent,
! 838: so expressions using it can be permanent too. */
! 839: exp = attr_eq (XSTR (exp, 0), XSTR (exp, 1));
! 840:
! 841: /* It shouldn't be possible to simplfy the value given to a
! 842: constant attribute, so don't expand this until it's time to
! 843: write the test expression. */
! 844: if (attr->is_const)
! 845: RTX_UNCHANGING_P (exp) = 1;
1.1 root 846:
847: if (attr->is_numeric)
848: {
849: for (p = XSTR (exp, 1); *p; p++)
850: if (*p < '0' || *p > '9')
851: fatal ("Attribute `%s' takes only numeric values",
852: XEXP (exp, 0));
853: }
854: else
855: {
856: for (av = attr->first_value; av; av = av->next)
857: if (GET_CODE (av->value) == CONST_STRING
858: && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0)))
859: break;
860:
861: if (av == NULL)
862: fatal ("Unknown value `%s' for `%s' attribute",
863: XEXP (exp, 1), XEXP (exp, 0));
864: }
865: }
866: else
867: {
868: /* Make an IOR tree of the possible values. */
869: orexp = false_rtx;
870: name_ptr = XSTR (exp, 1);
871: while ((p = next_comma_elt (&name_ptr)) != NULL)
872: {
1.1.1.3 ! root 873: newexp = attr_eq (XSTR (exp, 0), p);
1.1 root 874: orexp = insert_right_side (IOR, orexp, newexp, -2);
875: }
876:
1.1.1.2 root 877: return check_attr_test (orexp, is_const);
1.1 root 878: }
879: break;
880:
881: case CONST_INT:
882: /* Either TRUE or FALSE. */
883: if (XINT (exp, 0))
884: return true_rtx;
885: else
886: return false_rtx;
887:
888: case IOR:
889: case AND:
1.1.1.2 root 890: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const);
891: XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const);
1.1 root 892: break;
893:
894: case NOT:
1.1.1.2 root 895: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const);
1.1 root 896: break;
897:
898: case MATCH_OPERAND:
1.1.1.2 root 899: if (is_const)
900: fatal ("RTL operator \"%s\" not valid in constant attribute test",
901: GET_RTX_NAME (MATCH_OPERAND));
1.1.1.3 ! root 902: /* These cases can't be simplified. */
! 903: RTX_UNCHANGING_P (exp) = 1;
! 904: break;
1.1.1.2 root 905:
1.1 root 906: case LE: case LT: case GT: case GE:
907: case LEU: case LTU: case GTU: case GEU:
908: case NE: case EQ:
1.1.1.3 ! root 909: if (GET_CODE (XEXP (exp, 0)) == SYMBOL_REF
! 910: && GET_CODE (XEXP (exp, 1)) == SYMBOL_REF)
! 911: exp = attr_rtx (GET_CODE (exp),
! 912: attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 0), 0)),
! 913: attr_rtx (SYMBOL_REF, XSTR (XEXP (exp, 1), 0)));
1.1 root 914: /* These cases can't be simplified. */
915: RTX_UNCHANGING_P (exp) = 1;
916: break;
917:
1.1.1.2 root 918: case SYMBOL_REF:
919: if (is_const)
920: {
921: /* These cases are valid for constant attributes, but can't be
922: simplified. */
1.1.1.3 ! root 923: exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0));
1.1.1.2 root 924: RTX_UNCHANGING_P (exp) = 1;
925: break;
926: }
1.1 root 927: default:
928: fatal ("RTL operator \"%s\" not valid in attribute test",
929: GET_RTX_NAME (GET_CODE (exp)));
930: }
931:
932: return exp;
933: }
934:
935: /* Given an expression, ensure that it is validly formed and that all named
936: attribute values are valid for the given attribute. Issue a fatal error
1.1.1.3 ! root 937: if not. If no attribute is specified, assume a numeric attribute.
1.1 root 938:
1.1.1.3 ! root 939: Return a perhaps modified replacement expression for the value. */
! 940:
! 941: static rtx
1.1 root 942: check_attr_value (exp, attr)
943: rtx exp;
944: struct attr_desc *attr;
945: {
946: struct attr_value *av;
947: char *p;
948: int i;
949:
950: switch (GET_CODE (exp))
951: {
952: case CONST_INT:
953: if (attr && ! attr->is_numeric)
954: fatal ("CONST_INT not valid for non-numeric `%s' attribute",
955: attr->name);
956:
957: if (INTVAL (exp) < 0)
958: fatal ("Negative numeric value specified for `%s' attribute",
959: attr->name);
960:
961: break;
962:
963: case CONST_STRING:
964: if (! strcmp (XSTR (exp, 0), "*"))
965: break;
966:
967: if (attr == 0 || attr->is_numeric)
968: {
969: for (p = XSTR (exp, 0); *p; p++)
970: if (*p > '9' || *p < '0')
971: fatal ("Non-numeric value for numeric `%s' attribute",
1.1.1.3 ! root 972: attr ? attr->name : "internal");
1.1 root 973: break;
974: }
975:
976: for (av = attr->first_value; av; av = av->next)
977: if (GET_CODE (av->value) == CONST_STRING
978: && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0)))
979: break;
980:
981: if (av == NULL)
982: fatal ("Unknown value `%s' for `%s' attribute",
1.1.1.3 ! root 983: XSTR (exp, 0), attr ? attr->name : "internal");
1.1 root 984:
1.1.1.3 ! root 985: break;
1.1 root 986:
987: case IF_THEN_ELSE:
1.1.1.2 root 988: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0),
989: attr ? attr->is_const : 0);
1.1.1.3 ! root 990: XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
! 991: XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
! 992: break;
1.1 root 993:
994: case COND:
995: if (XVECLEN (exp, 0) % 2 != 0)
996: fatal ("First operand of COND must have even length");
997:
998: for (i = 0; i < XVECLEN (exp, 0); i += 2)
999: {
1.1.1.2 root 1000: XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i),
1001: attr ? attr->is_const : 0);
1.1.1.3 ! root 1002: XVECEXP (exp, 0, i + 1)
! 1003: = check_attr_value (XVECEXP (exp, 0, i + 1), attr);
1.1 root 1004: }
1005:
1.1.1.3 ! root 1006: XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr);
! 1007: break;
1.1 root 1008:
1.1.1.2 root 1009: case SYMBOL_REF:
1010: if (attr && attr->is_const)
1011: /* A constant SYMBOL_REF is valid as a constant attribute test and
1012: is expanded later by make_canonical into a COND. */
1.1.1.3 ! root 1013: return attr_rtx (SYMBOL_REF, XSTR (exp, 0));
1.1.1.2 root 1014: /* Otherwise, fall through... */
1015:
1.1 root 1016: default:
1017: fatal ("Illegal operation `%s' for attribute value",
1018: GET_RTX_NAME (GET_CODE (exp)));
1019: }
1.1.1.3 ! root 1020:
! 1021: return exp;
1.1 root 1022: }
1023:
1024: /* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET.
1025: It becomes a COND with each test being (eq_attr "alternative "n") */
1026:
1027: static rtx
1028: convert_set_attr_alternative (exp, num_alt, insn_code, insn_index)
1029: rtx exp;
1030: int num_alt;
1031: int insn_code, insn_index;
1032: {
1033: rtx newexp;
1034: rtx condexp;
1035: int i;
1036:
1037: if (XVECLEN (exp, 1) != num_alt)
1038: fatal ("Bad number of entries in SET_ATTR_ALTERNATIVE for insn %d",
1039: insn_index);
1040:
1041: /* Make a COND with all tests but the last. Select the last value via the
1042: default. */
1043: condexp = rtx_alloc (COND);
1044: XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
1045:
1046: for (i = 0; i < num_alt - 1; i++)
1047: {
1.1.1.2 root 1048: char *p;
1.1.1.3 ! root 1049: p = attr_numeral (i);
1.1.1.2 root 1050:
1.1.1.3 ! root 1051: XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p);
! 1052: #if 0
1.1.1.2 root 1053: /* Sharing this EQ_ATTR rtl causes trouble. */
1.1 root 1054: XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR);
1055: XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name;
1.1.1.2 root 1056: XSTR (XVECEXP (condexp, 0, 2 * i), 1) = p;
1.1.1.3 ! root 1057: #endif
1.1 root 1058: XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i);
1059: }
1060:
1061: XEXP (condexp, 1) = XVECEXP (exp, 1, i);
1062:
1.1.1.2 root 1063: return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), condexp);
1.1 root 1064: }
1065:
1066: /* Given a SET_ATTR, convert to the appropriate SET. If a comma-separated
1067: list of values is given, convert to SET_ATTR_ALTERNATIVE first. */
1068:
1069: static rtx
1070: convert_set_attr (exp, num_alt, insn_code, insn_index)
1071: rtx exp;
1072: int num_alt;
1073: int insn_code, insn_index;
1074: {
1075: rtx newexp;
1076: char *name_ptr;
1077: char *p;
1078: int n;
1079:
1080: /* See how many alternative specified. */
1081: n = n_comma_elts (XSTR (exp, 1));
1082: if (n == 1)
1.1.1.2 root 1083: return attr_rtx (SET,
1084: attr_rtx (ATTR, XSTR (exp, 0)),
1085: attr_rtx (CONST_STRING, XSTR (exp, 1)));
1.1 root 1086:
1087: newexp = rtx_alloc (SET_ATTR_ALTERNATIVE);
1088: XSTR (newexp, 0) = XSTR (exp, 0);
1089: XVEC (newexp, 1) = rtvec_alloc (n);
1090:
1091: /* Process each comma-separated name. */
1092: name_ptr = XSTR (exp, 1);
1093: n = 0;
1094: while ((p = next_comma_elt (&name_ptr)) != NULL)
1.1.1.2 root 1095: XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p);
1.1 root 1096:
1097: return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index);
1098: }
1099:
1100: /* Scan all definitions, checking for validity. Also, convert any SET_ATTR
1101: and SET_ATTR_ALTERNATIVE expressions to the corresponding SET
1102: expressions. */
1103:
1104: static void
1105: check_defs ()
1106: {
1107: struct insn_def *id;
1108: struct attr_desc *attr;
1109: int i;
1110: rtx value;
1111:
1112: for (id = defs; id; id = id->next)
1113: {
1114: if (XVEC (id->def, id->vec_idx) == NULL)
1115: continue;
1116:
1117: for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
1118: {
1119: value = XVECEXP (id->def, id->vec_idx, i);
1120: switch (GET_CODE (value))
1121: {
1122: case SET:
1123: if (GET_CODE (XEXP (value, 0)) != ATTR)
1124: fatal ("Bad attribute set in pattern %d", id->insn_index);
1125: break;
1126:
1127: case SET_ATTR_ALTERNATIVE:
1128: value = convert_set_attr_alternative (value,
1129: id->num_alternatives,
1130: id->insn_code,
1131: id->insn_index);
1132: break;
1133:
1134: case SET_ATTR:
1135: value = convert_set_attr (value, id->num_alternatives,
1136: id->insn_code, id->insn_index);
1137: break;
1138:
1139: default:
1140: fatal ("Invalid attribute code `%s' for pattern %d",
1141: GET_RTX_NAME (GET_CODE (value)), id->insn_index);
1142: }
1143:
1144: if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL)
1145: fatal ("Unknown attribute `%s' for pattern number %d",
1146: XSTR (XEXP (value, 0), 0), id->insn_index);
1147:
1148: XVECEXP (id->def, id->vec_idx, i) = value;
1.1.1.3 ! root 1149: XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr);
1.1 root 1150: }
1151: }
1152: }
1153:
1.1.1.2 root 1154: /* Given a constant SYMBOL_REF expression, convert to a COND that
1155: explicitly tests each enumerated value. */
1156:
1157: static rtx
1158: convert_const_symbol_ref (exp, attr)
1159: rtx exp;
1160: struct attr_desc *attr;
1161: {
1162: rtx condexp;
1163: struct attr_value *av;
1164: int i;
1165: int num_alt = 0;
1166:
1167: for (av = attr->first_value; av; av = av->next)
1168: num_alt++;
1169:
1170: /* Make a COND with all tests but the last, and in the original order.
1171: Select the last value via the default. Note that the attr values
1172: are constructed in reverse order. */
1173:
1174: condexp = rtx_alloc (COND);
1175: XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2);
1176: av = attr->first_value;
1177: XEXP (condexp, 1) = av->value;
1178:
1179: for (i = num_alt - 2; av = av->next, i >= 0; i--)
1180: {
1.1.1.3 ! root 1181: char *p, *string;
1.1.1.2 root 1182: rtx value;
1183:
1.1.1.3 ! root 1184: string = p = (char *) xmalloc (2
! 1185: + strlen (attr->name)
! 1186: + strlen (XSTR (av->value, 0)));
1.1.1.2 root 1187: strcpy (p, attr->name);
1188: strcat (p, "_");
1189: strcat (p, XSTR (av->value, 0));
1190: for (; *p != '\0'; p++)
1191: if (*p >= 'a' && *p <= 'z')
1192: *p -= 'a' - 'A';
1193:
1.1.1.3 ! root 1194: value = attr_rtx (SYMBOL_REF, string);
! 1195: RTX_UNCHANGING_P (value) = 1;
! 1196:
! 1197: XVECEXP (condexp, 0, 2 * i) = attr_rtx (EQ, exp, value);
! 1198:
1.1.1.2 root 1199: XVECEXP (condexp, 0, 2 * i + 1) = av->value;
1200: }
1201:
1202: return condexp;
1203: }
1204:
1.1 root 1205: /* Given a valid expression for an attribute value, remove any IF_THEN_ELSE
1206: expressions by converting them into a COND. This removes cases from this
1207: program. Also, replace an attribute value of "*" with the default attribute
1208: value. */
1209:
1210: static rtx
1211: make_canonical (attr, exp)
1212: struct attr_desc *attr;
1213: rtx exp;
1214: {
1215: int i;
1216: rtx newexp;
1217:
1218: switch (GET_CODE (exp))
1219: {
1220: case CONST_INT:
1221: exp = make_numeric_value (INTVAL (exp));
1222: break;
1223:
1224: case CONST_STRING:
1225: if (! strcmp (XSTR (exp, 0), "*"))
1226: {
1227: if (attr == 0 || attr->default_val == 0)
1228: fatal ("(attr_value \"*\") used in invalid context.");
1229: exp = attr->default_val->value;
1230: }
1231:
1232: break;
1233:
1.1.1.2 root 1234: case SYMBOL_REF:
1235: if (!attr->is_const || RTX_UNCHANGING_P (exp))
1236: break;
1.1.1.3 ! root 1237: /* The SYMBOL_REF is constant for a given run, so mark it as unchanging.
! 1238: This makes the COND something that won't be considered an arbitrary
! 1239: expression by walk_attr_value. */
1.1.1.2 root 1240: RTX_UNCHANGING_P (exp) = 1;
1241: exp = convert_const_symbol_ref (exp, attr);
1.1.1.3 ! root 1242: RTX_UNCHANGING_P (exp) = 1;
! 1243: exp = check_attr_value (exp, attr);
1.1.1.2 root 1244: /* Goto COND case since this is now a COND. Note that while the
1245: new expression is rescanned, all symbol_ref notes are mared as
1246: unchanging. */
1247: goto cond;
1248:
1.1 root 1249: case IF_THEN_ELSE:
1250: newexp = rtx_alloc (COND);
1251: XVEC (newexp, 0) = rtvec_alloc (2);
1252: XVECEXP (newexp, 0, 0) = XEXP (exp, 0);
1253: XVECEXP (newexp, 0, 1) = XEXP (exp, 1);
1254:
1255: XEXP (newexp, 1) = XEXP (exp, 2);
1256:
1257: exp = newexp;
1258: /* Fall through to COND case since this is now a COND. */
1259:
1260: case COND:
1.1.1.2 root 1261: cond:
1.1.1.3 ! root 1262: {
! 1263: int allsame = 1;
! 1264: rtx defval;
1.1 root 1265:
1.1.1.3 ! root 1266: /* First, check for degenerate COND. */
! 1267: if (XVECLEN (exp, 0) == 0)
! 1268: return make_canonical (attr, XEXP (exp, 1));
! 1269: defval = XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1));
1.1 root 1270:
1.1.1.3 ! root 1271: for (i = 0; i < XVECLEN (exp, 0); i += 2)
! 1272: {
! 1273: XVECEXP (exp, 0, i) = copy_boolean (XVECEXP (exp, 0, i));
! 1274: XVECEXP (exp, 0, i + 1)
! 1275: = make_canonical (attr, XVECEXP (exp, 0, i + 1));
! 1276: if (! rtx_equal_p (XVECEXP (exp, 0, i + 1), defval))
! 1277: allsame = 0;
! 1278: }
! 1279: if (allsame)
! 1280: return defval;
! 1281: break;
! 1282: }
1.1 root 1283: }
1284:
1285: return exp;
1286: }
1.1.1.3 ! root 1287:
! 1288: static rtx
! 1289: copy_boolean (exp)
! 1290: rtx exp;
! 1291: {
! 1292: if (GET_CODE (exp) == AND || GET_CODE (exp) == IOR)
! 1293: return attr_rtx (GET_CODE (exp), copy_boolean (XEXP (exp, 0)),
! 1294: copy_boolean (XEXP (exp, 1)));
! 1295: return exp;
! 1296: }
1.1 root 1297:
1298: /* Given a value and an attribute description, return a `struct attr_value *'
1299: that represents that value. This is either an existing structure, if the
1300: value has been previously encountered, or a newly-created structure.
1301:
1302: `insn_code' is the code of an insn whose attribute has the specified
1303: value (-2 if not processing an insn). We ensure that all insns for
1304: a given value have the same number of alternatives if the value checks
1305: alternatives. */
1306:
1307: static struct attr_value *
1308: get_attr_value (value, attr, insn_code)
1309: rtx value;
1310: struct attr_desc *attr;
1311: int insn_code;
1312: {
1313: struct attr_value *av;
1314: int num_alt = 0;
1315:
1316: value = make_canonical (attr, value);
1317: if (compares_alternatives_p (value))
1318: {
1319: if (insn_code < 0 || insn_alternatives == NULL)
1320: fatal ("(eq_attr \"alternatives\" ...) used in non-insn context");
1321: else
1322: num_alt = insn_alternatives[insn_code];
1323: }
1324:
1325: for (av = attr->first_value; av; av = av->next)
1326: if (rtx_equal_p (value, av->value)
1327: && (num_alt == 0 || av->first_insn == NULL
1328: || insn_alternatives[av->first_insn->insn_code]))
1329: return av;
1330:
1331: av = (struct attr_value *) xmalloc (sizeof (struct attr_value));
1332: av->value = value;
1333: av->next = attr->first_value;
1334: attr->first_value = av;
1335: av->first_insn = NULL;
1336: av->num_insns = 0;
1337: av->has_asm_insn = 0;
1338:
1339: return av;
1340: }
1341:
1342: /* After all DEFINE_DELAYs have been read in, create internal attributes
1343: to generate the required routines.
1344:
1345: First, we compute the number of delay slots for each insn (as a COND of
1346: each of the test expressions in DEFINE_DELAYs). Then, if more than one
1347: delay type is specified, we compute a similar function giving the
1348: DEFINE_DELAY ordinal for each insn.
1349:
1350: Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that
1351: tells whether a given insn can be in that delay slot.
1352:
1.1.1.3 ! root 1353: Normal attribute filling and optimization expands these to contain the
1.1 root 1354: information needed to handle delay slots. */
1355:
1356: static void
1357: expand_delays ()
1358: {
1359: struct delay_desc *delay;
1360: rtx condexp;
1361: rtx newexp;
1362: int i;
1363: char *p;
1364:
1365: /* First, generate data for `num_delay_slots' function. */
1366:
1367: condexp = rtx_alloc (COND);
1368: XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1369: XEXP (condexp, 1) = make_numeric_value (0);
1370:
1371: for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
1372: {
1373: XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1374: XVECEXP (condexp, 0, i + 1)
1375: = make_numeric_value (XVECLEN (delay->def, 1) / 3);
1376: }
1377:
1378: make_internal_attr ("*num_delay_slots", condexp, 0);
1379:
1380: /* If more than one delay type, do the same for computing the delay type. */
1381: if (num_delays > 1)
1382: {
1383: condexp = rtx_alloc (COND);
1384: XVEC (condexp, 0) = rtvec_alloc (num_delays * 2);
1385: XEXP (condexp, 1) = make_numeric_value (0);
1386:
1387: for (i = 0, delay = delays; delay; i += 2, delay = delay->next)
1388: {
1389: XVECEXP (condexp, 0, i) = XEXP (delay->def, 0);
1390: XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num);
1391: }
1392:
1393: make_internal_attr ("*delay_type", condexp, 1);
1394: }
1395:
1.1.1.3 ! root 1396: /* For each delay possibility and delay slot, compute an eligibility
! 1397: attribute for non-annulled insns and for each type of annulled (annul
1.1 root 1398: if true and annul if false). */
1399: for (delay = delays; delay; delay = delay->next)
1400: {
1401: for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
1402: {
1403: condexp = XVECEXP (delay->def, 1, i);
1404: if (condexp == 0) condexp = false_rtx;
1.1.1.2 root 1405: newexp = attr_rtx (IF_THEN_ELSE, condexp,
1406: make_numeric_value (1), make_numeric_value (0));
1.1 root 1407:
1.1.1.2 root 1408: p = attr_printf (13, "*delay_%d_%d", delay->num, i / 3);
1.1 root 1409: make_internal_attr (p, newexp, 1);
1410:
1411: if (have_annul_true)
1412: {
1413: condexp = XVECEXP (delay->def, 1, i + 1);
1414: if (condexp == 0) condexp = false_rtx;
1.1.1.2 root 1415: newexp = attr_rtx (IF_THEN_ELSE, condexp,
1416: make_numeric_value (1),
1417: make_numeric_value (0));
1418: p = attr_printf (18, "*annul_true_%d_%d", delay->num, i / 3);
1.1 root 1419: make_internal_attr (p, newexp, 1);
1420: }
1421:
1422: if (have_annul_false)
1423: {
1424: condexp = XVECEXP (delay->def, 1, i + 2);
1425: if (condexp == 0) condexp = false_rtx;
1.1.1.2 root 1426: newexp = attr_rtx (IF_THEN_ELSE, condexp,
1427: make_numeric_value (1),
1428: make_numeric_value (0));
1429: p = attr_printf (18, "*annul_false_%d_%d", delay->num, i / 3);
1.1 root 1430: make_internal_attr (p, newexp, 1);
1431: }
1432: }
1433: }
1434: }
1435:
1436: /* This function is given a left and right side expression and an operator.
1437: Each side is a conditional expression, each alternative of which has a
1438: numerical value. The function returns another conditional expression
1439: which, for every possible set of condition values, returns a value that is
1440: the operator applied to the values of the two sides.
1441:
1442: Since this is called early, it must also support IF_THEN_ELSE. */
1443:
1444: static rtx
1445: operate_exp (op, left, right)
1446: enum operator op;
1447: rtx left, right;
1448: {
1449: int left_value, right_value;
1450: rtx newexp;
1451: int i;
1452:
1453: /* If left is a string, apply operator to it and the right side. */
1454: if (GET_CODE (left) == CONST_STRING)
1455: {
1456: /* If right is also a string, just perform the operation. */
1457: if (GET_CODE (right) == CONST_STRING)
1458: {
1459: left_value = atoi (XSTR (left, 0));
1460: right_value = atoi (XSTR (right, 0));
1461: switch (op)
1462: {
1463: case PLUS_OP:
1464: i = left_value + right_value;
1465: break;
1466:
1467: case MINUS_OP:
1468: i = left_value - right_value;
1469: break;
1470:
1471: case OR_OP:
1472: i = left_value | right_value;
1473: break;
1474:
1475: case MAX_OP:
1476: if (left_value > right_value)
1477: i = left_value;
1478: else
1479: i = right_value;
1480: break;
1481:
1482: default:
1483: abort ();
1484: }
1485:
1486: return make_numeric_value (i);
1487: }
1488: else if (GET_CODE (right) == IF_THEN_ELSE)
1489: {
1490: /* Apply recursively to all values within. */
1.1.1.3 ! root 1491: rtx newleft = operate_exp (op, left, XEXP (right, 1));
! 1492: rtx newright = operate_exp (op, left, XEXP (right, 2));
! 1493: if (rtx_equal_p (newleft, newright))
! 1494: return newleft;
! 1495: return attr_rtx (IF_THEN_ELSE, XEXP (right, 0), newleft, newright);
1.1 root 1496: }
1497: else if (GET_CODE (right) == COND)
1498: {
1.1.1.3 ! root 1499: int allsame = 1;
! 1500: rtx defval;
! 1501:
1.1 root 1502: newexp = rtx_alloc (COND);
1503: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0));
1.1.1.3 ! root 1504: defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1));
! 1505:
1.1 root 1506: for (i = 0; i < XVECLEN (right, 0); i += 2)
1507: {
1508: XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i);
1509: XVECEXP (newexp, 0, i + 1)
1510: = operate_exp (op, left, XVECEXP (right, 0, i + 1));
1.1.1.3 ! root 1511: if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
! 1512: defval))
! 1513: allsame = 0;
1.1 root 1514: }
1515:
1.1.1.3 ! root 1516: /* If the resulting cond is trivial (all alternatives
! 1517: give the same value), optimize it away. */
! 1518: if (allsame)
! 1519: {
! 1520: obstack_free (rtl_obstack, newexp);
! 1521: return operate_exp (op, left, XEXP (right, 1));
! 1522: }
! 1523:
! 1524: /* If the result is the same as the RIGHT operand,
! 1525: just use that. */
! 1526: if (rtx_equal_p (newexp, right))
! 1527: {
! 1528: obstack_free (rtl_obstack, newexp);
! 1529: return right;
! 1530: }
1.1 root 1531:
1532: return newexp;
1533: }
1534: else
1535: fatal ("Badly formed attribute value");
1536: }
1537:
1538: /* Otherwise, do recursion the other way. */
1539: else if (GET_CODE (left) == IF_THEN_ELSE)
1540: {
1.1.1.3 ! root 1541: rtx newleft = operate_exp (op, XEXP (left, 1), right);
! 1542: rtx newright = operate_exp (op, XEXP (left, 2), right);
! 1543: if (rtx_equal_p (newleft, newright))
! 1544: return newleft;
! 1545: return attr_rtx (IF_THEN_ELSE, XEXP (left, 0), newleft, newright);
1.1 root 1546: }
1547: else if (GET_CODE (left) == COND)
1548: {
1.1.1.3 ! root 1549: int allsame = 1;
! 1550: rtx defval;
! 1551:
1.1 root 1552: newexp = rtx_alloc (COND);
1553: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0));
1.1.1.3 ! root 1554: defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right);
! 1555:
1.1 root 1556: for (i = 0; i < XVECLEN (left, 0); i += 2)
1557: {
1558: XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i);
1559: XVECEXP (newexp, 0, i + 1)
1560: = operate_exp (op, XVECEXP (left, 0, i + 1), right);
1.1.1.3 ! root 1561: if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1),
! 1562: defval))
! 1563: allsame = 0;
1.1 root 1564: }
1565:
1.1.1.3 ! root 1566: /* If the cond is trivial (all alternatives give the same value),
! 1567: optimize it away. */
! 1568: if (allsame)
! 1569: {
! 1570: obstack_free (rtl_obstack, newexp);
! 1571: return operate_exp (op, XEXP (left, 1), right);
! 1572: }
! 1573:
! 1574: /* If the result is the same as the LEFT operand,
! 1575: just use that. */
! 1576: if (rtx_equal_p (newexp, left))
! 1577: {
! 1578: obstack_free (rtl_obstack, newexp);
! 1579: return left;
! 1580: }
1.1 root 1581:
1582: return newexp;
1583: }
1584:
1585: else
1586: fatal ("Badly formed attribute value.");
1587: /* NOTREACHED */
1588: return NULL;
1589: }
1590:
1591: /* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we
1592: construct a number of attributes.
1593:
1594: The first produces a function `function_units_used' which is given an
1595: insn and produces a mask showing which function units are required for
1596: the execution of that insn.
1597:
1598: The second produces a function `result_ready_cost' which is used to
1599: determine the time that the result of an insn will be ready and hence
1600: a worst-case schedule.
1601:
1602: Both of these produce quite complex expressions which are then set as the
1603: default value of internal attributes. Normal attribute simplification
1604: should produce reasonable expressions.
1605:
1606: For each unit, a `<name>_unit_ready_cost' function will take an
1607: insn and give the delay until that unit will be ready with the result
1608: and a `<name>_unit_busy_delay' function is given an insn already
1609: executing on the unit and a candidate to execute and will give the
1610: cost from the time the executing insn started until the candidate
1611: can start (ignore limitations on the number of simultaneous insns). */
1612:
1613: static void
1614: expand_units ()
1615: {
1616: struct function_unit *unit;
1617: struct function_unit_op *op;
1618: rtx unitsmask;
1619: rtx readycost;
1620: rtx newexp;
1621: char *str;
1622:
1623: /* Initially, cost and masks are zero. */
1624: unitsmask = readycost = make_numeric_value (0);
1625:
1626: /* Set up a conditional for costs and unit mask. */
1627: newexp = rtx_alloc (IF_THEN_ELSE);
1628: XEXP (newexp, 2) = make_numeric_value (0);
1629:
1630: /* For each unit, insert its contribution to the above three values. */
1631: for (unit = units; unit; unit = unit->next)
1632: {
1633: /* An expression that computes the ready cost for this unit. */
1634: rtx readyexp = rtx_alloc (COND);
1635: /* An expression that maps insns to operation number for conflicts. */
1636: rtx caseexp = rtx_alloc (COND);
1637:
1638: XVEC (readyexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
1639: XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2);
1640:
1641: for (op = unit->ops; op; op = op->next)
1642: {
1643: /* Validate the expressions we were given for the conditions
1644: and busy cost. Then make an attribute for use in the conflict
1645: function. */
1.1.1.2 root 1646: op->condexp = check_attr_test (op->condexp, 0);
1.1.1.3 ! root 1647: op->busyexp = check_attr_value (op->busyexp, 0);
1.1.1.2 root 1648: str = attr_printf (strlen (unit->name) + 11, "*%s_case_%d",
1649: unit->name, op->num);
1.1 root 1650: make_internal_attr (str, make_canonical (0, op->busyexp));
1651:
1652: /* Make our adjustment to the two COND's being computed. If we are
1653: the last operation class, place our values into the default of
1654: the COND. */
1655: if (op->num == unit->num_opclasses - 1)
1656: {
1657: XEXP (readyexp, 1) = make_numeric_value (op->ready);
1658: XEXP (caseexp, 1) = make_numeric_value (op->num);
1659: }
1660: else
1661: {
1662: XVECEXP (readyexp, 0, op->num * 2) = op->condexp;
1663: XVECEXP (readyexp, 0, op->num * 2 + 1)
1664: = make_numeric_value (op->ready);
1665: XVECEXP (caseexp, 0, op->num * 2) = op->condexp;
1666: XVECEXP (caseexp, 0, op->num * 2 + 1)
1667: = make_numeric_value (op->num);
1668: }
1669: }
1670:
1671: /* Make an attribute for the case number and ready delay. */
1.1.1.2 root 1672: str = attr_printf (strlen (unit->name) + 8, "*%s_cases", unit->name);
1.1 root 1673: make_internal_attr (str, caseexp, 1);
1674:
1.1.1.2 root 1675: str = attr_printf (strlen (unit->name) + 20, "*%s_unit_ready_cost",
1676: unit->name);
1.1 root 1677: make_internal_attr (str, readyexp, 0);
1678:
1679: /* Merge this function unit into the ready cost and unit mask
1680: attributes. */
1.1.1.2 root 1681: XEXP (newexp, 0) = check_attr_test (unit->condexp, 0);
1.1 root 1682: XEXP (newexp, 1) = make_numeric_value (1 << unit->num);
1683: unitsmask = operate_exp (OR_OP, unitsmask, newexp);
1684:
1685: XEXP (newexp, 1) = readyexp;
1686: readycost = operate_exp (MAX_OP, readycost, newexp);
1687: }
1688:
1689: make_internal_attr ("*function_units_used", unitsmask, 0);
1690: make_internal_attr ("*result_ready_cost", readycost, 0);
1691: }
1692:
1693: /* Once all attributes and insns have been read and checked, we construct for
1694: each attribute value a list of all the insns that have that value for
1695: the attribute. */
1696:
1697: static void
1698: fill_attr (attr)
1699: struct attr_desc *attr;
1700: {
1701: struct attr_value *av;
1702: struct insn_ent *ie;
1703: struct insn_def *id;
1704: int i;
1705: rtx value;
1706:
1.1.1.3 ! root 1707: /* Don't fill constant attributes. The value is independent of
! 1708: any particular insn. */
! 1709: if (attr->is_const)
! 1710: return;
! 1711:
1.1 root 1712: for (id = defs; id; id = id->next)
1713: {
1714: /* If no value is specified for this insn for this attribute, use the
1715: default. */
1716: value = NULL;
1717: if (XVEC (id->def, id->vec_idx))
1718: for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++)
1719: if (! strcmp (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0),
1720: attr->name))
1721: value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1);
1722:
1723: if (value == NULL)
1724: av = attr->default_val;
1725: else
1726: av = get_attr_value (value, attr, id->insn_code);
1727:
1728: ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent));
1729: ie->insn_code = id->insn_code;
1730: ie->insn_index = id->insn_code;
1731: insert_insn_ent (av, ie);
1732: }
1733: }
1734:
1735: /* Given an expression EXP, see if it is a COND or IF_THEN_ELSE that has a
1736: test that checks relative positions of insns (uses MATCH_DUP or PC).
1737: If so, replace it with what is obtained by passing the expression to
1738: ADDRESS_FN. If not but it is a COND or IF_THEN_ELSE, call this routine
1739: recursively on each value (including the default value). Otherwise,
1740: return the value returned by NO_ADDRESS_FN applied to EXP. */
1741:
1742: static rtx
1743: substitute_address (exp, no_address_fn, address_fn)
1744: rtx exp;
1745: rtx (*no_address_fn) ();
1746: rtx (*address_fn) ();
1747: {
1748: int i;
1749: rtx newexp;
1750:
1751: if (GET_CODE (exp) == COND)
1752: {
1753: /* See if any tests use addresses. */
1754: address_used = 0;
1755: for (i = 0; i < XVECLEN (exp, 0); i += 2)
1756: walk_attr_value (XVECEXP (exp, 0, i));
1757:
1758: if (address_used)
1759: return (*address_fn) (exp);
1760:
1761: /* Make a new copy of this COND, replacing each element. */
1762: newexp = rtx_alloc (COND);
1763: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0));
1764: for (i = 0; i < XVECLEN (exp, 0); i += 2)
1765: {
1766: XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i);
1767: XVECEXP (newexp, 0, i + 1)
1768: = substitute_address (XVECEXP (exp, 0, i + 1),
1769: no_address_fn, address_fn);
1770: }
1771:
1772: XEXP (newexp, 1) = substitute_address (XEXP (exp, 1),
1773: no_address_fn, address_fn);
1774:
1775: return newexp;
1776: }
1777:
1778: else if (GET_CODE (exp) == IF_THEN_ELSE)
1779: {
1780: address_used = 0;
1781: walk_attr_value (XEXP (exp, 0));
1782: if (address_used)
1783: return (*address_fn) (exp);
1784:
1.1.1.2 root 1785: return attr_rtx (IF_THEN_ELSE,
1786: substitute_address (XEXP (exp, 0),
1787: no_address_fn, address_fn),
1788: substitute_address (XEXP (exp, 1),
1789: no_address_fn, address_fn),
1790: substitute_address (XEXP (exp, 2),
1791: no_address_fn, address_fn));
1.1 root 1792: }
1793:
1794: return (*no_address_fn) (exp);
1795: }
1796:
1797: /* Make new attributes from the `length' attribute. The following are made,
1798: each corresponding to a function called from `shorten_branches' or
1799: `get_attr_length':
1800:
1801: *insn_default_length This is the length of the insn to be returned
1802: by `get_attr_length' before `shorten_branches'
1803: has been called. In each case where the length
1804: depends on relative addresses, the largest
1805: possible is used. This routine is also used
1806: to compute the initial size of the insn.
1807:
1808: *insn_variable_length_p This returns 1 if the insn's length depends
1809: on relative addresses, zero otherwise.
1810:
1811: *insn_current_length This is only called when it is known that the
1812: insn has a variable length and returns the
1813: current length, based on relative addresses.
1814: */
1815:
1816: static void
1817: make_length_attrs ()
1818: {
1819: static char *new_names[] = {"*insn_default_length",
1820: "*insn_variable_length_p",
1821: "*insn_current_length"};
1822: static rtx (*no_address_fn[]) () = {identity_fn, zero_fn, zero_fn};
1823: static rtx (*address_fn[]) () = {max_fn, one_fn, identity_fn};
1824: int i;
1825: struct attr_desc *length_attr, *new_attr;
1826: struct attr_value *av, *new_av;
1827: struct insn_ent *ie, *new_ie;
1828:
1829: /* See if length attribute is defined. If so, it must be numeric. Make
1830: it special so we don't output anything for it. */
1831: length_attr = find_attr ("length", 0);
1832: if (length_attr == 0)
1833: return;
1834:
1835: if (! length_attr->is_numeric)
1836: fatal ("length attribute must be numeric.");
1837:
1.1.1.2 root 1838: length_attr->is_const = 0;
1.1 root 1839: length_attr->is_special = 1;
1840:
1841: /* Make each new attribute, in turn. */
1842: for (i = 0; i < sizeof new_names / sizeof new_names[0]; i++)
1843: {
1844: make_internal_attr (new_names[i],
1845: substitute_address (length_attr->default_val->value,
1846: no_address_fn[i], address_fn[i]),
1847: 0);
1848: new_attr = find_attr (new_names[i], 0);
1849: for (av = length_attr->first_value; av; av = av->next)
1850: for (ie = av->first_insn; ie; ie = ie->next)
1851: {
1852: new_av = get_attr_value (substitute_address (av->value,
1853: no_address_fn[i],
1854: address_fn[i]),
1855: new_attr, ie->insn_code);
1856: new_ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent));
1857: new_ie->insn_code = ie->insn_code;
1858: new_ie->insn_index = ie->insn_index;
1859: insert_insn_ent (new_av, new_ie);
1860: }
1861: }
1862: }
1863:
1864: /* Utility functions called from above routine. */
1865:
1866: static rtx
1867: identity_fn (exp)
1868: rtx exp;
1869: {
1870: return exp;
1871: }
1872:
1873: static rtx
1874: zero_fn (exp)
1875: rtx exp;
1876: {
1877: return make_numeric_value (0);
1878: }
1879:
1880: static rtx
1881: one_fn (exp)
1882: rtx exp;
1883: {
1884: return make_numeric_value (1);
1885: }
1886:
1887: static rtx
1888: max_fn (exp)
1889: rtx exp;
1890: {
1891: return make_numeric_value (max_attr_value (exp));
1892: }
1893:
1894: /* Take a COND expression and see if any of the conditions in it can be
1895: simplified. If any are known true or known false for the particular insn
1896: code, the COND can be further simplified.
1897:
1898: Also call ourselves on any COND operations that are values of this COND.
1899:
1.1.1.3 ! root 1900: We do not modify EXP; rather, we make and return a new rtx. */
1.1 root 1901:
1902: static rtx
1903: simplify_cond (exp, insn_code, insn_index)
1904: rtx exp;
1905: int insn_code, insn_index;
1906: {
1907: int i, j;
1.1.1.3 ! root 1908: /* We store the desired contents here,
! 1909: then build a new expression if they don't match EXP. */
! 1910: rtx defval = XEXP (exp, 1);
! 1911: rtx new_defval = XEXP (exp, 1);
! 1912:
! 1913: int len = XVECLEN (exp, 0);
! 1914: rtx *tests = (rtx *) alloca (len * sizeof (rtx));
! 1915: int allsame = 1;
! 1916: char *spacer, *first_spacer;
! 1917:
! 1918: /* This lets us free all storage allocated below, if appropriate. */
! 1919: first_spacer = (char *) obstack_finish (rtl_obstack);
! 1920:
! 1921: bcopy (&XVECEXP (exp, 0, 0), tests, len * sizeof (rtx));
! 1922:
! 1923: /* See if default value needs simplification. */
! 1924: if (GET_CODE (defval) == COND)
! 1925: new_defval = simplify_cond (defval, insn_code, insn_index);
1.1 root 1926:
1.1.1.3 ! root 1927: /* Simplify the subexpressions, and see what tests we can get rid of. */
! 1928:
! 1929: for (i = 0; i < len; i += 2)
1.1 root 1930: {
1.1.1.3 ! root 1931: rtx newtest, newval;
! 1932:
! 1933: /* Simplify this test. */
! 1934: newtest = SIMPLIFY_TEST_EXP (tests[i], insn_code, insn_index);
! 1935: tests[i] = newtest;
! 1936:
! 1937: newval = tests[i + 1];
! 1938: /* See if this value may need simplification. */
! 1939: if (GET_CODE (newval) == COND)
! 1940: newval = simplify_cond (newval, insn_code, insn_index);
! 1941:
! 1942: /* Look for ways to delete or combine this test. */
1.1 root 1943: if (newtest == true_rtx)
1944: {
1.1.1.3 ! root 1945: /* If test is true, make this value the default
! 1946: and discard this + any following tests. */
! 1947: len = i;
! 1948: defval = tests[i + 1];
! 1949: new_defval = newval;
1.1 root 1950: }
1951:
1952: else if (newtest == false_rtx)
1953: {
1.1.1.3 ! root 1954: /* If test is false, discard it and its value. */
! 1955: for (j = i; j < len - 2; j++)
! 1956: tests[j] = tests[j + 2];
! 1957: len -= 2;
1.1 root 1958: }
1959:
1.1.1.3 ! root 1960: else if (i > 0 && attr_equal_p (newval, tests[i - 1]))
1.1 root 1961: {
1.1.1.3 ! root 1962: /* If this value and the value for the prev test are the same,
! 1963: merge the tests. */
1.1 root 1964:
1.1.1.3 ! root 1965: tests[i - 2]
! 1966: = insert_right_side (IOR, tests[i - 2], newtest,
1.1 root 1967: insn_code, insn_index);
1968:
1.1.1.3 ! root 1969: /* Delete this test/value. */
! 1970: for (j = i; j < len - 2; j++)
! 1971: tests[j] = tests[j + 2];
! 1972: len -= 2;
1.1 root 1973: }
1974:
1.1.1.3 ! root 1975: else
! 1976: tests[i + 1] = newval;
! 1977: }
1.1 root 1978:
1.1.1.3 ! root 1979: /* If the last test in a COND has the same value
! 1980: as the default value, that test isn't needed. */
1.1 root 1981:
1.1.1.3 ! root 1982: while (len > 0 && attr_equal_p (tests[len - 1], new_defval))
! 1983: len -= 2;
1.1 root 1984:
1.1.1.3 ! root 1985: /* See if we changed anything. */
! 1986: if (len != XVECLEN (exp, 0) || new_defval != XEXP (exp, 1))
! 1987: allsame = 0;
! 1988: else
! 1989: for (i = 0; i < len; i++)
! 1990: if (! attr_equal_p (tests[i], XVECEXP (exp, 0, i)))
! 1991: {
! 1992: allsame = 0;
1.1 root 1993: break;
1994: }
1995:
1.1.1.3 ! root 1996: if (len == 0)
1.1 root 1997: {
1.1.1.3 ! root 1998: obstack_free (rtl_obstack, first_spacer);
! 1999: if (GET_CODE (defval) == COND)
! 2000: return simplify_cond (defval, insn_code, insn_index);
! 2001: return defval;
! 2002: }
! 2003: else if (allsame)
! 2004: {
! 2005: obstack_free (rtl_obstack, first_spacer);
! 2006: return exp;
1.1 root 2007: }
2008: else
1.1.1.3 ! root 2009: {
! 2010: rtx newexp = rtx_alloc (COND);
! 2011:
! 2012: XVEC (newexp, 0) = rtvec_alloc (len);
! 2013: bcopy (tests, &XVECEXP (newexp, 0, 0), len * sizeof (rtx));
! 2014: XEXP (newexp, 1) = new_defval;
! 2015: return newexp;
! 2016: }
1.1 root 2017: }
2018:
2019: /* Remove an insn entry from an attribute value. */
2020:
2021: static void
2022: remove_insn_ent (av, ie)
2023: struct attr_value *av;
2024: struct insn_ent *ie;
2025: {
2026: struct insn_ent *previe;
2027:
2028: if (av->first_insn == ie)
2029: av->first_insn = ie->next;
2030: else
2031: {
2032: for (previe = av->first_insn; previe->next != ie; previe = previe->next)
2033: ;
2034: previe->next = ie->next;
2035: }
2036:
2037: av->num_insns--;
2038: if (ie->insn_code == -1)
2039: av->has_asm_insn = 0;
2040: }
2041:
2042: /* Insert an insn entry in an attribute value list. */
2043:
2044: static void
2045: insert_insn_ent (av, ie)
2046: struct attr_value *av;
2047: struct insn_ent *ie;
2048: {
2049: ie->next = av->first_insn;
2050: av->first_insn = ie;
2051: av->num_insns++;
2052: if (ie->insn_code == -1)
2053: av->has_asm_insn = 1;
2054: }
2055:
2056: /* This is a utility routine to take an expression that is a tree of either
2057: AND or IOR expressions and insert a new term. The new term will be
2058: inserted at the right side of the first node whose code does not match
2059: the root. A new node will be created with the root's code. Its left
2060: side will be the old right side and its right side will be the new
2061: term.
2062:
2063: If the `term' is itself a tree, all its leaves will be inserted. */
2064:
2065: static rtx
2066: insert_right_side (code, exp, term, insn_code, insn_index)
2067: RTX_CODE code;
2068: rtx exp;
2069: rtx term;
2070: int insn_code, insn_index;
2071: {
2072: rtx newexp;
2073:
1.1.1.3 ! root 2074: /* Avoid consing in some special cases. */
! 2075: if (code == AND && term == true_rtx)
! 2076: return exp;
! 2077: if (code == AND && term == false_rtx)
! 2078: return false_rtx;
! 2079: if (code == AND && exp == true_rtx)
! 2080: return term;
! 2081: if (code == AND && exp == false_rtx)
! 2082: return false_rtx;
! 2083: if (code == IOR && term == true_rtx)
! 2084: return true_rtx;
! 2085: if (code == IOR && term == false_rtx)
! 2086: return exp;
! 2087: if (code == IOR && exp == true_rtx)
! 2088: return true_rtx;
! 2089: if (code == IOR && exp == false_rtx)
! 2090: return term;
! 2091: if (attr_equal_p (exp, term))
! 2092: return exp;
! 2093:
1.1 root 2094: if (GET_CODE (term) == code)
2095: {
2096: exp = insert_right_side (code, exp, XEXP (term, 0),
2097: insn_code, insn_index);
2098: exp = insert_right_side (code, exp, XEXP (term, 1),
2099: insn_code, insn_index);
2100:
2101: return exp;
2102: }
2103:
2104: if (GET_CODE (exp) == code)
2105: {
1.1.1.3 ! root 2106: rtx new = insert_right_side (code, XEXP (exp, 1),
! 2107: term, insn_code, insn_index);
! 2108: if (new != XEXP (exp, 1))
! 2109: /* Make a copy of this expression and call recursively. */
! 2110: newexp = attr_rtx (code, XEXP (exp, 0), new);
! 2111: else
! 2112: newexp = exp;
1.1 root 2113: }
2114: else
2115: {
2116: /* Insert the new term. */
1.1.1.2 root 2117: newexp = attr_rtx (code, exp, term);
1.1.1.3 ! root 2118: }
1.1 root 2119:
2120: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2121: }
2122:
2123: /* If we have an expression which AND's a bunch of
2124: (not (eq_attrq "alternative" "n"))
2125: terms, we may have covered all or all but one of the possible alternatives.
2126: If so, we can optimize. Similarly for IOR's of EQ_ATTR.
2127:
2128: This routine is passed an expression and either AND or IOR. It returns a
1.1.1.3 ! root 2129: bitmask indicating which alternatives are present.
! 2130: ??? What does "present" mean? */
1.1 root 2131:
2132: static int
2133: compute_alternative_mask (exp, code)
2134: rtx exp;
2135: RTX_CODE code;
2136: {
1.1.1.3 ! root 2137: char *string;
1.1 root 2138: if (GET_CODE (exp) == code)
2139: return compute_alternative_mask (XEXP (exp, 0), code)
2140: | compute_alternative_mask (XEXP (exp, 1), code);
2141:
2142: else if (code == AND && GET_CODE (exp) == NOT
2143: && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
2144: && XSTR (XEXP (exp, 0), 0) == alternative_name)
1.1.1.3 ! root 2145: string = XSTR (XEXP (exp, 0), 1);
1.1 root 2146:
2147: else if (code == IOR && GET_CODE (exp) == EQ_ATTR
2148: && XSTR (exp, 0) == alternative_name)
1.1.1.3 ! root 2149: string = XSTR (exp, 1);
1.1 root 2150:
2151: else
2152: return 0;
1.1.1.3 ! root 2153:
! 2154: if (string[1] == 0)
! 2155: return 1 << (string[0] - '0');
! 2156: return 1 << atoi (string);
1.1 root 2157: }
2158:
2159: /* Given I, a single-bit mask, return RTX to compare the `alternative'
2160: attribute with the value represented by that bit. */
2161:
2162: static rtx
2163: make_alternative_compare (mask)
2164: int mask;
2165: {
2166: rtx newexp;
2167: int i;
2168: char *alternative;
2169:
2170: /* Find the bit. */
2171: for (i = 0; (mask & (1 << i)) == 0; i++)
2172: ;
2173:
1.1.1.3 ! root 2174: newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i));
1.1 root 2175: RTX_UNCHANGING_P (newexp) = 1;
2176:
2177: return newexp;
2178: }
2179:
2180: /* If we are processing an (eq_attr "attr" "value") test, we find the value
2181: of "attr" for this insn code. From that value, we can compute a test
2182: showing when the EQ_ATTR will be true. This routine performs that
2183: computation. If a test condition involves an address, we leave the EQ_ATTR
2184: intact because addresses are only valid for the `length' attribute. */
2185:
1.1.1.3 ! root 2186: /* ??? Kenner, document the meanings of the arguments!!! */
! 2187:
1.1 root 2188: static rtx
2189: evaluate_eq_attr (exp, value, insn_code, insn_index)
2190: rtx exp;
2191: rtx value;
2192: int insn_code, insn_index;
2193: {
2194: rtx orexp, andexp;
2195: rtx right;
2196: rtx newexp;
2197: int i;
2198:
2199: if (GET_CODE (value) == CONST_STRING)
2200: {
2201: if (! strcmp (XSTR (value, 0), XSTR (exp, 1)))
2202: newexp = true_rtx;
2203: else
2204: newexp = false_rtx;
2205: }
2206: else if (GET_CODE (value) == COND)
2207: {
2208: /* We construct an IOR of all the cases for which the requested attribute
2209: value is present. Since we start with FALSE, if it is not present,
2210: FALSE will be returned.
2211:
2212: Each case is the AND of the NOT's of the previous conditions with the
2213: current condition; in the default case the current condition is TRUE.
2214:
2215: For each possible COND value, call ourselves recursively.
2216:
2217: The extra TRUE and FALSE expressions will be eliminated by another
2218: call to the simplification routine. */
2219:
2220: orexp = false_rtx;
2221: andexp = true_rtx;
2222:
1.1.1.3 ! root 2223: if (current_alternative_string)
! 2224: clear_struct_flag (value);
! 2225:
1.1 root 2226: for (i = 0; i < XVECLEN (value, 0); i += 2)
2227: {
1.1.1.3 ! root 2228: rtx this = SIMPLIFY_TEST_EXP (XVECEXP (value, 0, i),
! 2229: insn_code, insn_index);
! 2230:
! 2231: SIMPLIFY_ALTERNATIVE (this);
! 2232:
! 2233: right = insert_right_side (AND, andexp, this,
1.1 root 2234: insn_code, insn_index);
2235: right = insert_right_side (AND, right,
2236: evaluate_eq_attr (exp, XVECEXP (value, 0, i + 1),
2237: insn_code, insn_index),
2238: insn_code, insn_index);
2239: orexp = insert_right_side (IOR, orexp, right,
2240: insn_code, insn_index);
2241:
2242: /* Add this condition into the AND expression. */
1.1.1.3 ! root 2243: newexp = attr_rtx (NOT, this);
1.1 root 2244: andexp = insert_right_side (AND, andexp, newexp,
2245: insn_code, insn_index);
2246: }
2247:
2248: /* Handle the default case. */
2249: right = insert_right_side (AND, andexp,
2250: evaluate_eq_attr (exp, XEXP (value, 1),
2251: insn_code, insn_index),
2252: insn_code, insn_index);
2253: newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index);
2254: }
2255: else
2256: abort ();
2257:
1.1.1.3 ! root 2258: /* If uses an address, must return original expression. But set the
! 2259: RTX_UNCHANGING_P bit so we don't try to simplify it again. */
1.1 root 2260:
2261: address_used = 0;
2262: walk_attr_value (newexp);
2263:
2264: if (address_used)
1.1.1.3 ! root 2265: {
! 2266: /* This had `&& current_alternative_string', which seems to be wrong. */
! 2267: if (! RTX_UNCHANGING_P (exp))
! 2268: return copy_rtx_unchanging (exp);
! 2269: return exp;
! 2270: }
1.1 root 2271: else
2272: return newexp;
2273: }
2274:
2275: /* This routine is called when an AND of a term with a tree of AND's is
2276: encountered. If the term or its complement is present in the tree, it
2277: can be replaced with TRUE or FALSE, respectively.
2278:
2279: Note that (eq_attr "att" "v1") and (eq_attr "att" "v2") cannot both
2280: be true and hence are complementary.
2281:
2282: There is one special case: If we see
2283: (and (not (eq_attr "att" "v1"))
2284: (eq_attr "att" "v2"))
2285: this can be replaced by (eq_attr "att" "v2"). To do this we need to
2286: replace the term, not anything in the AND tree. So we pass a pointer to
2287: the term. */
2288:
2289: static rtx
2290: simplify_and_tree (exp, pterm, insn_code, insn_index)
2291: rtx exp;
2292: rtx *pterm;
2293: int insn_code, insn_index;
2294: {
2295: rtx left, right;
2296: rtx newexp;
2297: rtx temp;
2298: int left_eliminates_term, right_eliminates_term;
2299:
2300: if (GET_CODE (exp) == AND)
2301: {
2302: left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
2303: right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
2304: if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2305: {
1.1.1.2 root 2306: newexp = attr_rtx (GET_CODE (exp), left, right);
1.1 root 2307:
2308: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2309: }
2310: }
2311:
2312: else if (GET_CODE (exp) == IOR)
2313: {
2314: /* For the IOR case, we do the same as above, except that we can
2315: only eliminate `term' if both sides of the IOR would do so. */
2316: temp = *pterm;
2317: left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
2318: left_eliminates_term = (temp == true_rtx);
2319:
2320: temp = *pterm;
2321: right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
2322: right_eliminates_term = (temp == true_rtx);
2323:
2324: if (left_eliminates_term && right_eliminates_term)
2325: *pterm = true_rtx;
2326:
2327: if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2328: {
1.1.1.2 root 2329: newexp = attr_rtx (GET_CODE (exp), left, right);
1.1 root 2330:
2331: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2332: }
2333: }
2334:
2335: /* Check for simplifications. Do some extra checking here since this
2336: routine is called so many times. */
2337:
2338: if (exp == *pterm)
2339: return true_rtx;
2340:
2341: else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm)
2342: return false_rtx;
2343:
2344: else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0))
2345: return false_rtx;
2346:
2347: else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR)
2348: {
2349: if (XSTR (exp, 0) != XSTR (*pterm, 0))
2350: return exp;
2351:
2352: if (! strcmp (XSTR (exp, 1), XSTR (*pterm, 1)))
2353: return true_rtx;
2354: else
2355: return false_rtx;
2356: }
2357:
2358: else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
2359: && GET_CODE (XEXP (exp, 0)) == EQ_ATTR)
2360: {
2361: if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0))
2362: return exp;
2363:
2364: if (! strcmp (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1)))
2365: return false_rtx;
2366: else
2367: return true_rtx;
2368: }
2369:
2370: else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
2371: && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR)
2372: {
2373: if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0))
2374: return exp;
2375:
2376: if (! strcmp (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1)))
2377: return false_rtx;
2378: else
2379: *pterm = true_rtx;
2380: }
2381:
2382: else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT)
2383: {
1.1.1.3 ! root 2384: if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0)))
1.1 root 2385: return true_rtx;
2386: }
2387:
2388: else if (GET_CODE (exp) == NOT)
2389: {
1.1.1.3 ! root 2390: if (attr_equal_p (XEXP (exp, 0), *pterm))
1.1 root 2391: return false_rtx;
2392: }
2393:
2394: else if (GET_CODE (*pterm) == NOT)
2395: {
1.1.1.3 ! root 2396: if (attr_equal_p (XEXP (*pterm, 0), exp))
1.1 root 2397: return false_rtx;
2398: }
2399:
1.1.1.3 ! root 2400: else if (attr_equal_p (exp, *pterm))
1.1 root 2401: return true_rtx;
2402:
2403: return exp;
2404: }
2405:
1.1.1.3 ! root 2406: /* Similar to `simplify_and_tree', but for IOR trees. */
1.1 root 2407:
2408: static rtx
2409: simplify_or_tree (exp, pterm, insn_code, insn_index)
2410: rtx exp;
2411: rtx *pterm;
2412: int insn_code, insn_index;
2413: {
2414: rtx left, right;
2415: rtx newexp;
2416: rtx temp;
2417: int left_eliminates_term, right_eliminates_term;
2418:
2419: if (GET_CODE (exp) == IOR)
2420: {
2421: left = simplify_or_tree (XEXP (exp, 0), pterm, insn_code, insn_index);
2422: right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index);
2423: if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2424: {
1.1.1.2 root 2425: newexp = attr_rtx (GET_CODE (exp), left, right);
1.1 root 2426:
2427: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2428: }
2429: }
2430:
2431: else if (GET_CODE (exp) == AND)
2432: {
2433: /* For the AND case, we do the same as above, except that we can
2434: only eliminate `term' if both sides of the AND would do so. */
2435: temp = *pterm;
2436: left = simplify_or_tree (XEXP (exp, 0), &temp, insn_code, insn_index);
2437: left_eliminates_term = (temp == false_rtx);
2438:
2439: temp = *pterm;
2440: right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index);
2441: right_eliminates_term = (temp == false_rtx);
2442:
2443: if (left_eliminates_term && right_eliminates_term)
2444: *pterm = false_rtx;
2445:
2446: if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2447: {
1.1.1.2 root 2448: newexp = attr_rtx (GET_CODE (exp), left, right);
1.1 root 2449:
2450: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2451: }
2452: }
2453:
1.1.1.3 ! root 2454: if (attr_equal_p (exp, *pterm))
1.1 root 2455: return false_rtx;
2456:
1.1.1.3 ! root 2457: else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm))
1.1 root 2458: return true_rtx;
2459:
1.1.1.3 ! root 2460: else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp))
1.1 root 2461: return true_rtx;
2462:
2463: else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT
2464: && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
2465: && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0))
2466: *pterm = false_rtx;
2467:
2468: else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT
2469: && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR
2470: && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0))
2471: return false_rtx;
2472:
2473: return exp;
2474: }
2475:
2476: /* Given an expression, see if it can be simplified for a particular insn
2477: code based on the values of other attributes being tested. This can
2478: eliminate nested get_attr_... calls.
2479:
2480: Note that if an endless recursion is specified in the patterns, the
2481: optimization will loop. However, it will do so in precisely the cases where
2482: an infinite recursion loop could occur during compilation. It's better that
2483: it occurs here! */
2484:
2485: static rtx
2486: simplify_test_exp (exp, insn_code, insn_index)
2487: rtx exp;
2488: int insn_code, insn_index;
2489: {
2490: rtx left, right;
2491: struct attr_desc *attr;
2492: struct attr_value *av;
2493: struct insn_ent *ie;
2494: int i;
2495: rtx newexp = exp;
1.1.1.3 ! root 2496: char *spacer = (char *) obstack_finish (rtl_obstack);
! 2497:
! 2498: static rtx loser = 0;
! 2499: static int count = 0;
! 2500: static stopcount = 0;
! 2501:
! 2502: if (exp == loser)
! 2503: do_nothing ();
! 2504: count++;
! 2505: if (count == stopcount)
! 2506: do_nothing ();
! 2507:
! 2508: /* Don't re-simplify something we already simplified. */
! 2509: if (RTX_UNCHANGING_P (exp) || MEM_IN_STRUCT_P (exp))
! 2510: return exp;
1.1 root 2511:
2512: switch (GET_CODE (exp))
2513: {
2514: case AND:
2515: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
1.1.1.3 ! root 2516: SIMPLIFY_ALTERNATIVE (left);
! 2517: if (left == false_rtx)
! 2518: {
! 2519: obstack_free (rtl_obstack, spacer);
! 2520: return false_rtx;
! 2521: }
1.1 root 2522: right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
1.1.1.3 ! root 2523: SIMPLIFY_ALTERNATIVE (right);
! 2524: if (left == false_rtx)
! 2525: {
! 2526: obstack_free (rtl_obstack, spacer);
! 2527: return false_rtx;
! 2528: }
1.1 root 2529:
2530: /* If either side is an IOR and we have (eq_attr "alternative" ..")
2531: present on both sides, apply the distributive law since this will
1.1.1.2 root 2532: yield simplifications. */
1.1 root 2533: if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
2534: && compute_alternative_mask (left, IOR)
2535: && compute_alternative_mask (right, IOR))
2536: {
2537: if (GET_CODE (left) == IOR)
2538: {
2539: rtx tem = left;
2540: left = right;
2541: right = tem;
2542: }
2543:
1.1.1.2 root 2544: newexp = attr_rtx (IOR,
2545: attr_rtx (AND, left, XEXP (right, 0)),
2546: attr_rtx (AND, left, XEXP (right, 1)));
1.1 root 2547:
2548: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2549: }
2550:
2551: /* Try with the term on both sides. */
2552: right = simplify_and_tree (right, &left, insn_code, insn_index);
2553: if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
2554: left = simplify_and_tree (left, &right, insn_code, insn_index);
2555:
2556: if (left == false_rtx || right == false_rtx)
1.1.1.3 ! root 2557: {
! 2558: obstack_free (rtl_obstack, spacer);
! 2559: return false_rtx;
! 2560: }
1.1 root 2561: else if (left == true_rtx)
1.1.1.3 ! root 2562: {
! 2563: return right;
! 2564: }
1.1 root 2565: else if (right == true_rtx)
1.1.1.3 ! root 2566: {
! 2567: return left;
! 2568: }
1.1 root 2569: /* See if all or all but one of the insn's alternatives are specified
2570: in this tree. Optimize if so. */
2571:
2572: else if (insn_code >= 0
2573: && (GET_CODE (left) == AND
2574: || (GET_CODE (left) == NOT
2575: && GET_CODE (XEXP (left, 0)) == EQ_ATTR
2576: && XSTR (XEXP (left, 0), 0) == alternative_name)
2577: || GET_CODE (right) == AND
2578: || (GET_CODE (right) == NOT
2579: && GET_CODE (XEXP (right, 0)) == EQ_ATTR
2580: && XSTR (XEXP (right, 0), 0) == alternative_name)))
2581: {
2582: i = compute_alternative_mask (exp, AND);
2583: if (i & ~insn_alternatives[insn_code])
2584: fatal ("Illegal alternative specified for pattern number %d",
2585: insn_index);
2586:
2587: /* If all alternatives are excluded, this is false. */
2588: i ^= insn_alternatives[insn_code];
2589: if (i == 0)
2590: return false_rtx;
2591: else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
2592: {
2593: /* If just one excluded, AND a comparison with that one to the
2594: front of the tree. The others will be eliminated by
2595: optimization. We do not want to do this if the insn has one
2596: alternative and we have tested none of them! */
2597: left = make_alternative_compare (i);
2598: right = simplify_and_tree (exp, &left, insn_code, insn_index);
1.1.1.2 root 2599: newexp = attr_rtx (AND, left, right);
1.1 root 2600:
2601: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2602: }
2603: }
2604:
2605: if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2606: {
1.1.1.2 root 2607: newexp = attr_rtx (AND, left, right);
1.1 root 2608: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2609: }
2610: break;
2611:
2612: case IOR:
2613: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
1.1.1.3 ! root 2614: SIMPLIFY_ALTERNATIVE (left);
! 2615: if (left == true_rtx)
! 2616: {
! 2617: obstack_free (rtl_obstack, spacer);
! 2618: return true_rtx;
! 2619: }
1.1 root 2620: right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index);
1.1.1.3 ! root 2621: SIMPLIFY_ALTERNATIVE (right);
! 2622: if (right == true_rtx)
! 2623: {
! 2624: obstack_free (rtl_obstack, spacer);
! 2625: return true_rtx;
! 2626: }
1.1 root 2627:
2628: right = simplify_or_tree (right, &left, insn_code, insn_index);
2629: if (left == XEXP (exp, 0) && right == XEXP (exp, 1))
2630: left = simplify_or_tree (left, &right, insn_code, insn_index);
2631:
2632: if (right == true_rtx || left == true_rtx)
1.1.1.3 ! root 2633: {
! 2634: obstack_free (rtl_obstack, spacer);
! 2635: return true_rtx;
! 2636: }
1.1 root 2637: else if (left == false_rtx)
1.1.1.3 ! root 2638: {
! 2639: return right;
! 2640: }
1.1 root 2641: else if (right == false_rtx)
1.1.1.3 ! root 2642: {
! 2643: return left;
! 2644: }
1.1 root 2645:
2646: /* Test for simple cases where the distributive law is useful. I.e.,
2647: convert (ior (and (x) (y))
2648: (and (x) (z)))
2649: to (and (x)
2650: (ior (y) (z)))
2651: */
2652:
2653: else if (GET_CODE (left) == AND && GET_CODE (right) == AND
1.1.1.3 ! root 2654: && attr_equal_p (XEXP (left, 0), XEXP (right, 0)))
1.1 root 2655: {
1.1.1.2 root 2656: newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1));
1.1 root 2657:
2658: left = XEXP (left, 0);
2659: right = newexp;
1.1.1.2 root 2660: newexp = attr_rtx (AND, left, right);
1.1 root 2661: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2662: }
2663:
2664: /* See if all or all but one of the insn's alternatives are specified
2665: in this tree. Optimize if so. */
2666:
2667: else if (insn_code >= 0
2668: && (GET_CODE (left) == IOR
2669: || (GET_CODE (left) == EQ_ATTR
2670: && XSTR (left, 0) == alternative_name)
2671: || GET_CODE (right) == IOR
2672: || (GET_CODE (right) == EQ_ATTR
2673: && XSTR (right, 0) == alternative_name)))
2674: {
2675: i = compute_alternative_mask (exp, IOR);
2676: if (i & ~insn_alternatives[insn_code])
2677: fatal ("Illegal alternative specified for pattern number %d",
2678: insn_index);
2679:
2680: /* If all alternatives are included, this is true. */
2681: i ^= insn_alternatives[insn_code];
2682: if (i == 0)
2683: return true_rtx;
2684: else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1)
2685: {
2686: /* If just one excluded, IOR a comparison with that one to the
2687: front of the tree. The others will be eliminated by
2688: optimization. We do not want to do this if the insn has one
2689: alternative and we have tested none of them! */
2690: left = make_alternative_compare (i);
2691: right = simplify_and_tree (exp, &left, insn_code, insn_index);
1.1.1.2 root 2692: newexp = attr_rtx (IOR, attr_rtx (NOT, left), right);
1.1 root 2693:
2694: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2695: }
2696: }
2697:
2698: if (left != XEXP (exp, 0) || right != XEXP (exp, 1))
2699: {
1.1.1.2 root 2700: newexp = attr_rtx (IOR, left, right);
1.1 root 2701: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2702: }
2703: break;
2704:
2705: case NOT:
1.1.1.3 ! root 2706: if (GET_CODE (XEXP (exp, 0)) == NOT)
! 2707: {
! 2708: left = SIMPLIFY_TEST_EXP (XEXP (XEXP (exp, 0), 0),
! 2709: insn_code, insn_index);
! 2710: SIMPLIFY_ALTERNATIVE (left);
! 2711: return left;
! 2712: }
! 2713:
1.1 root 2714: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index);
1.1.1.3 ! root 2715: SIMPLIFY_ALTERNATIVE (left);
1.1 root 2716: if (GET_CODE (left) == NOT)
2717: return XEXP (left, 0);
2718:
2719: if (left == false_rtx)
1.1.1.3 ! root 2720: {
! 2721: obstack_free (rtl_obstack, spacer);
! 2722: return true_rtx;
! 2723: }
1.1 root 2724: else if (left == true_rtx)
1.1.1.3 ! root 2725: {
! 2726: obstack_free (rtl_obstack, spacer);
! 2727: return false_rtx;
! 2728: }
1.1 root 2729:
2730: /* Try to apply De`Morgan's laws. */
2731: else if (GET_CODE (left) == IOR)
2732: {
1.1.1.2 root 2733: newexp = attr_rtx (AND,
2734: attr_rtx (NOT, XEXP (left, 0)),
2735: attr_rtx (NOT, XEXP (left, 1)));
1.1 root 2736:
2737: newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2738: }
2739: else if (GET_CODE (left) == AND)
2740: {
1.1.1.2 root 2741: newexp = attr_rtx (IOR,
2742: attr_rtx (NOT, XEXP (left, 0)),
2743: attr_rtx (NOT, XEXP (left, 1)));
1.1 root 2744:
2745: newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index);
2746: }
2747: else if (left != XEXP (exp, 0))
2748: {
1.1.1.2 root 2749: newexp = attr_rtx (NOT, left);
1.1 root 2750: }
2751: break;
2752:
2753: case EQ_ATTR:
1.1.1.3 ! root 2754: if (current_alternative_string && XSTR (exp, 0) == alternative_name)
! 2755: return (XSTR (exp, 1) == current_alternative_string
! 2756: ? true_rtx : false_rtx);
! 2757:
1.1 root 2758: /* Look at the value for this insn code in the specified attribute.
2759: We normally can replace this comparison with the condition that
2760: would give this insn the values being tested for. */
2761: if (XSTR (exp, 0) != alternative_name
2762: && (attr = find_attr (XSTR (exp, 0), 0)) != NULL)
2763: for (av = attr->first_value; av; av = av->next)
2764: for (ie = av->first_insn; ie; ie = ie->next)
2765: if (ie->insn_code == insn_code)
2766: return evaluate_eq_attr (exp, av->value, insn_code, insn_index);
2767: }
2768:
2769: /* We have already simplified this expression. Simplifying it again
2770: won't buy anything unless we weren't given a valid insn code
2771: to process (i.e., we are canonicalizing something.). */
1.1.1.3 ! root 2772: if (insn_code != -2 /* Seems wrong: && current_alternative_string. */
! 2773: && ! RTX_UNCHANGING_P (newexp))
! 2774: return copy_rtx_unchanging (newexp);
1.1 root 2775:
2776: return newexp;
2777: }
1.1.1.3 ! root 2778:
! 2779: do_nothing ()
! 2780: {}
1.1 root 2781:
2782: /* Optimize the attribute lists by seeing if we can determine conditional
2783: values from the known values of other attributes. This will save subroutine
2784: calls during the compilation. */
2785:
2786: static void
2787: optimize_attrs ()
2788: {
2789: struct attr_desc *attr;
2790: struct attr_value *av;
2791: struct insn_ent *ie, *nextie;
2792: rtx newexp;
2793: int something_changed = 1;
1.1.1.3 ! root 2794: int i;
! 2795: struct attr_value_list { struct attr_value *av;
! 2796: struct insn_ent *ie;
! 2797: struct attr_desc * attr;
! 2798: struct attr_value_list *next; };
! 2799: struct attr_value_list **insn_code_values;
! 2800: struct attr_value_list *iv;
! 2801:
! 2802: /* For each insn code, make a list of all the insn_ent's for it,
! 2803: for all values for all attributes. */
! 2804:
! 2805: /* Make 2 extra elements, for "code" values -2 and -1. */
! 2806: insn_code_values
! 2807: = (struct attr_value_list **) alloca ((insn_code_number + 2)
! 2808: * sizeof (struct attr_value_list *));
! 2809: bzero (insn_code_values,
! 2810: (insn_code_number + 2) * sizeof (struct attr_value_list *));
! 2811: /* Offset the table address so we can index by -2 or -1. */
! 2812: insn_code_values += 2;
1.1 root 2813:
1.1.1.3 ! root 2814: for (i = 0; i < MAX_ATTRS_INDEX; i++)
! 2815: for (attr = attrs[i]; attr; attr = attr->next)
! 2816: for (av = attr->first_value; av; av = av->next)
! 2817: for (ie = av->first_insn; ie; ie = ie->next)
! 2818: {
! 2819: iv = ((struct attr_value_list *)
! 2820: alloca (sizeof (struct attr_value_list)));
! 2821: iv->attr = attr;
! 2822: iv->av = av;
! 2823: iv->ie = ie;
! 2824: iv->next = insn_code_values[ie->insn_code];
! 2825: insn_code_values[ie->insn_code] = iv;
! 2826: }
! 2827:
! 2828: /* Process one insn code at a time. */
! 2829: for (i = -2; i < insn_code_number; i++)
1.1 root 2830: {
1.1.1.3 ! root 2831: /* Clear the MEM_IN_STRUCT_P flag everywhere relevant.
! 2832: We use it to mean "already simplified for this insn". */
! 2833: for (iv = insn_code_values[i]; iv; iv = iv->next)
! 2834: clear_struct_flag (iv->av->value);
! 2835:
! 2836: /* Loop until nothing changes for one iteration. */
! 2837: something_changed = 1;
! 2838: while (something_changed)
! 2839: {
! 2840: something_changed = 0;
! 2841: for (iv = insn_code_values[i]; iv; iv = iv->next)
! 2842: {
! 2843: struct obstack *old = rtl_obstack;
! 2844: char *spacer = (char *) obstack_finish (temp_obstack);
1.1 root 2845:
1.1.1.3 ! root 2846: attr = iv->attr;
! 2847: av = iv->av;
! 2848: ie = iv->ie;
! 2849: if (GET_CODE (av->value) != COND)
! 2850: continue;
! 2851:
! 2852: rtl_obstack = temp_obstack;
! 2853: #if 0 /* This was intended as a speed up, but it was slower. */
! 2854: if (insn_n_alternatives[ie->insn_code] > 6
! 2855: && count_sub_rtxs (av->value, 200) >= 200)
! 2856: newexp = simplify_by_alternatives (av->value, ie->insn_code,
! 2857: ie->insn_index);
! 2858: else
! 2859: #endif
1.1 root 2860: newexp = simplify_cond (av->value, ie->insn_code,
2861: ie->insn_index);
1.1.1.3 ! root 2862:
! 2863: rtl_obstack = old;
! 2864: if (newexp != av->value)
! 2865: {
! 2866: newexp = attr_copy_rtx (newexp);
! 2867: remove_insn_ent (av, ie);
! 2868: av = get_attr_value (newexp, attr, ie->insn_code);
! 2869: iv->av = av;
! 2870: insert_insn_ent (av, ie);
! 2871: something_changed = 1;
! 2872: }
! 2873: obstack_free (temp_obstack, spacer);
! 2874: }
! 2875: }
1.1 root 2876: }
2877: }
1.1.1.3 ! root 2878:
! 2879: static rtx
! 2880: simplify_by_alternatives (exp, insn_code, insn_index)
! 2881: rtx exp;
! 2882: int insn_code, insn_index;
! 2883: {
! 2884: int i;
! 2885: int len = insn_n_alternatives[insn_code];
! 2886: rtx newexp = rtx_alloc (COND);
! 2887: rtx ultimate;
! 2888:
! 2889:
! 2890: XVEC (newexp, 0) = rtvec_alloc (len * 2);
! 2891:
! 2892: /* It will not matter what value we use as the default value
! 2893: of the new COND, since that default will never be used.
! 2894: Choose something of the right type. */
! 2895: for (ultimate = exp; GET_CODE (ultimate) == COND;)
! 2896: ultimate = XEXP (ultimate, 1);
! 2897: XEXP (newexp, 1) = ultimate;
! 2898:
! 2899: for (i = 0; i < insn_n_alternatives[insn_code]; i++)
! 2900: {
! 2901: current_alternative_string = attr_numeral (i);
! 2902: XVECEXP (newexp, 0, i * 2) = make_alternative_compare (1 << i);
! 2903: XVECEXP (newexp, 0, i * 2 + 1)
! 2904: = simplify_cond (exp, insn_code, insn_index);
! 2905: }
! 2906:
! 2907: current_alternative_string = 0;
! 2908: return simplify_cond (newexp, insn_code, insn_index);
! 2909: }
! 2910:
! 2911: /* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */
! 2912:
! 2913: clear_struct_flag (x)
! 2914: rtx x;
! 2915: {
! 2916: register int i;
! 2917: register int j;
! 2918: register enum rtx_code code;
! 2919: register char *fmt;
! 2920:
! 2921: MEM_IN_STRUCT_P (x) = 0;
! 2922: if (RTX_UNCHANGING_P (x))
! 2923: return;
! 2924:
! 2925: code = GET_CODE (x);
! 2926:
! 2927: switch (code)
! 2928: {
! 2929: case REG:
! 2930: case QUEUED:
! 2931: case CONST_INT:
! 2932: case CONST_DOUBLE:
! 2933: case SYMBOL_REF:
! 2934: case CODE_LABEL:
! 2935: case PC:
! 2936: case CC0:
! 2937: case EQ_ATTR:
! 2938: return;
! 2939: }
! 2940:
! 2941: /* Compare the elements. If any pair of corresponding elements
! 2942: fail to match, return 0 for the whole things. */
! 2943:
! 2944: fmt = GET_RTX_FORMAT (code);
! 2945: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
! 2946: {
! 2947: switch (fmt[i])
! 2948: {
! 2949: case 'V':
! 2950: case 'E':
! 2951: for (j = 0; j < XVECLEN (x, i); j++)
! 2952: clear_struct_flag (XVECEXP (x, i, j));
! 2953: break;
! 2954:
! 2955: case 'e':
! 2956: clear_struct_flag (XEXP (x, i));
! 2957: break;
! 2958: }
! 2959: }
! 2960: }
! 2961:
! 2962: /* Return the number of RTX objects making up the expression X.
! 2963: But if we count more more than MAX objects, stop counting. */
! 2964:
! 2965: count_sub_rtxs (x, max)
! 2966: rtx x;
! 2967: int max;
! 2968: {
! 2969: register int i;
! 2970: register int j;
! 2971: register enum rtx_code code;
! 2972: register char *fmt;
! 2973: int total = 0;
! 2974:
! 2975: code = GET_CODE (x);
! 2976:
! 2977: switch (code)
! 2978: {
! 2979: case REG:
! 2980: case QUEUED:
! 2981: case CONST_INT:
! 2982: case CONST_DOUBLE:
! 2983: case SYMBOL_REF:
! 2984: case CODE_LABEL:
! 2985: case PC:
! 2986: case CC0:
! 2987: case EQ_ATTR:
! 2988: return 1;
! 2989: }
! 2990:
! 2991: /* Compare the elements. If any pair of corresponding elements
! 2992: fail to match, return 0 for the whole things. */
! 2993:
! 2994: fmt = GET_RTX_FORMAT (code);
! 2995: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
! 2996: {
! 2997: if (total >= max)
! 2998: return total;
! 2999:
! 3000: switch (fmt[i])
! 3001: {
! 3002: case 'V':
! 3003: case 'E':
! 3004: for (j = 0; j < XVECLEN (x, i); j++)
! 3005: total += count_sub_rtxs (XVECEXP (x, i, j), max);
! 3006: break;
! 3007:
! 3008: case 'e':
! 3009: total += count_sub_rtxs (XEXP (x, i), max);
! 3010: break;
! 3011: }
! 3012: }
! 3013: return total;
! 3014:
! 3015: }
1.1 root 3016:
3017: /* Create table entries for DEFINE_ATTR. */
3018:
3019: static void
3020: gen_attr (exp)
3021: rtx exp;
3022: {
3023: struct attr_desc *attr;
3024: struct attr_value *av;
3025: char *name_ptr;
3026: char *p;
3027:
3028: /* Make a new attribute structure. Check for duplicate by looking at
3029: attr->default_val, since it is initialized by this routine. */
3030: attr = find_attr (XSTR (exp, 0), 1);
3031: if (attr->default_val)
3032: fatal ("Duplicate definition for `%s' attribute", attr->name);
3033:
3034: if (*XSTR (exp, 1) == '\0')
3035: attr->is_numeric = 1;
3036: else
3037: {
3038: name_ptr = XSTR (exp, 1);
3039: while ((p = next_comma_elt (&name_ptr)) != NULL)
3040: {
3041: av = (struct attr_value *) xmalloc (sizeof (struct attr_value));
1.1.1.2 root 3042: av->value = attr_rtx (CONST_STRING, p);
1.1 root 3043: av->next = attr->first_value;
3044: attr->first_value = av;
3045: av->first_insn = NULL;
3046: av->num_insns = 0;
3047: av->has_asm_insn = 0;
3048: }
3049: }
3050:
1.1.1.2 root 3051: if (GET_CODE (XEXP (exp, 2)) == CONST)
3052: {
3053: attr->is_const = 1;
3054: if (attr->is_numeric)
3055: fatal ("Constant attributes may not take numeric values");
3056: /* Get rid of the CONST node. It is allowed only at top-level. */
3057: XEXP (exp, 2) = XEXP (XEXP (exp, 2), 0);
3058: }
3059:
1.1 root 3060: if (! strcmp (attr->name, "length") && ! attr->is_numeric)
3061: fatal ("`length' attribute must take numeric values");
3062:
3063: /* Set up the default value. */
1.1.1.3 ! root 3064: XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr);
1.1 root 3065: attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2);
3066: }
3067:
3068: /* Given a pattern for DEFINE_PEEPHOLE or DEFINE_INSN, return the number of
3069: alternatives in the constraints. Assume all MATCH_OPERANDs have the same
3070: number of alternatives as this should be checked elsewhere. */
3071:
3072: static int
3073: count_alternatives (exp)
3074: rtx exp;
3075: {
3076: int i, j, n;
3077: char *fmt;
3078:
3079: if (GET_CODE (exp) == MATCH_OPERAND)
3080: return n_comma_elts (XSTR (exp, 2));
3081:
3082: for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
3083: i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
3084: switch (*fmt++)
3085: {
3086: case 'e':
3087: case 'u':
3088: n = count_alternatives (XEXP (exp, i));
3089: if (n)
3090: return n;
3091: break;
3092:
3093: case 'E':
3094: case 'V':
3095: if (XVEC (exp, i) != NULL)
3096: for (j = 0; j < XVECLEN (exp, i); j++)
3097: {
3098: n = count_alternatives (XVECEXP (exp, i, j));
3099: if (n)
3100: return n;
3101: }
3102: }
3103:
3104: return 0;
3105: }
3106:
3107: /* Returns non-zero if the given expression contains an EQ_ATTR with the
3108: `alternative' attribute. */
3109:
3110: static int
3111: compares_alternatives_p (exp)
3112: rtx exp;
3113: {
3114: int i, j;
3115: char *fmt;
3116:
3117: if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name)
3118: return 1;
3119:
3120: for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
3121: i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
3122: switch (*fmt++)
3123: {
3124: case 'e':
3125: case 'u':
3126: if (compares_alternatives_p (XEXP (exp, i)))
3127: return 1;
3128: break;
3129:
3130: case 'E':
3131: for (j = 0; j < XVECLEN (exp, i); j++)
3132: if (compares_alternatives_p (XVECEXP (exp, i, j)))
3133: return 1;
3134: break;
3135: }
3136:
3137: return 0;
3138: }
3139:
3140: /* Returns non-zero is INNER is contained in EXP. */
3141:
3142: static int
3143: contained_in_p (inner, exp)
3144: rtx inner;
3145: rtx exp;
3146: {
3147: int i, j;
3148: char *fmt;
3149:
3150: if (rtx_equal_p (inner, exp))
3151: return 1;
3152:
3153: for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp));
3154: i < GET_RTX_LENGTH (GET_CODE (exp)); i++)
3155: switch (*fmt++)
3156: {
3157: case 'e':
3158: case 'u':
3159: if (contained_in_p (inner, XEXP (exp, i)))
3160: return 1;
3161: break;
3162:
3163: case 'E':
3164: for (j = 0; j < XVECLEN (exp, i); j++)
3165: if (contained_in_p (inner, XVECEXP (exp, i, j)))
3166: return 1;
3167: break;
3168: }
3169:
3170: return 0;
3171: }
3172:
3173: /* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES. */
3174:
3175: static void
3176: gen_insn (exp)
3177: rtx exp;
3178: {
3179: struct insn_def *id;
3180:
3181: id = (struct insn_def *) xmalloc (sizeof (struct insn_def));
3182: id->next = defs;
3183: defs = id;
3184: id->def = exp;
3185:
3186: switch (GET_CODE (exp))
3187: {
3188: case DEFINE_INSN:
3189: id->insn_code = insn_code_number++;
3190: id->insn_index = insn_index_number++;
3191: id->num_alternatives = count_alternatives (exp);
3192: if (id->num_alternatives == 0)
3193: id->num_alternatives = 1;
3194: id->vec_idx = 4;
3195: break;
3196:
3197: case DEFINE_PEEPHOLE:
3198: id->insn_code = insn_code_number++;
3199: id->insn_index = insn_index_number++;
3200: id->num_alternatives = count_alternatives (exp);
3201: if (id->num_alternatives == 0)
3202: id->num_alternatives = 1;
3203: id->vec_idx = 3;
3204: break;
3205:
3206: case DEFINE_ASM_ATTRIBUTES:
3207: id->insn_code = -1;
3208: id->insn_index = -1;
3209: id->num_alternatives = 1;
3210: id->vec_idx = 0;
3211: got_define_asm_attributes = 1;
3212: break;
3213: }
3214: }
3215:
3216: /* Process a DEFINE_DELAY. Validate the vector length, check if annul
3217: true or annul false is specified, and make a `struct delay_desc'. */
3218:
3219: static void
3220: gen_delay (def)
3221: rtx def;
3222: {
3223: struct delay_desc *delay;
3224: int i;
3225:
3226: if (XVECLEN (def, 1) % 3 != 0)
3227: fatal ("Number of elements in DEFINE_DELAY must be multiple of three.");
3228:
3229: for (i = 0; i < XVECLEN (def, 1); i += 3)
3230: {
3231: if (XVECEXP (def, 1, i + 1))
3232: have_annul_true = 1;
3233: if (XVECEXP (def, 1, i + 2))
3234: have_annul_false = 1;
3235: }
3236:
3237: delay = (struct delay_desc *) xmalloc (sizeof (struct delay_desc));
3238: delay->def = def;
3239: delay->num = ++num_delays;
3240: delay->next = delays;
3241: delays = delay;
3242: }
3243:
3244: /* Process a DEFINE_FUNCTION_UNIT.
3245:
3246: This gives information about a function unit contained in the CPU.
3247: We fill in a `struct function_unit_op' and a `struct function_unit'
3248: with information used later by `expand_unit'. */
3249:
3250: static void
3251: gen_unit (def)
3252: rtx def;
3253: {
3254: struct function_unit *unit;
3255: struct function_unit_op *op;
3256:
3257: /* See if we have already seen this function unit. If so, check that
1.1.1.3 ! root 3258: the multiplicity and simultaneity values are the same. If not, make
1.1 root 3259: a structure for this function unit. */
3260: for (unit = units; unit; unit = unit->next)
3261: if (! strcmp (unit->name, XSTR (def, 0)))
3262: {
3263: if (unit->multiplicity != XINT (def, 1)
3264: || unit->simultaneity != XINT (def, 2))
3265: fatal ("Differing specifications given for `%s' function unit.",
3266: unit->name);
3267: break;
3268: }
3269:
3270: if (unit == 0)
3271: {
3272: unit = (struct function_unit *) xmalloc (sizeof (struct function_unit));
3273: unit->name = XSTR (def, 0);
3274: unit->multiplicity = XINT (def, 1);
3275: unit->simultaneity = XINT (def, 2);
3276: unit->num = num_units++;
3277: unit->num_opclasses = 0;
3278: unit->condexp = false_rtx;
3279: unit->ops = 0;
3280: unit->next = units;
3281: units = unit;
3282: }
3283:
3284: /* Make a new operation class structure entry and initialize it. */
3285: op = (struct function_unit_op *) xmalloc (sizeof (struct function_unit_op));
3286: op->condexp = XEXP (def, 3);
3287: op->num = unit->num_opclasses++;
3288: op->ready = XINT (def, 4);
3289: op->next = unit->ops;
3290: unit->ops = op;
3291:
3292: /* Set our busy expression based on whether or not an optional conflict
3293: vector was specified. */
3294: if (XVEC (def, 6))
3295: {
3296: /* Compute the IOR of all the specified expressions. */
3297: rtx orexp = false_rtx;
3298: int i;
3299:
3300: for (i = 0; i < XVECLEN (def, 6); i++)
3301: orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2);
3302:
1.1.1.2 root 3303: op->busyexp = attr_rtx (IF_THEN_ELSE, orexp,
3304: make_numeric_value (XINT (def, 5)),
3305: make_numeric_value (0));
1.1 root 3306: }
3307: else
3308: op->busyexp = make_numeric_value (XINT (def, 5));
3309:
3310: /* Merge our conditional into that of the function unit so we can determine
3311: which insns are used by the function unit. */
3312: unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2);
3313: }
3314:
3315: /* Given a piece of RTX, print a C expression to test it's truth value.
3316: We use AND and IOR both for logical and bit-wise operations, so
3317: interpret them as logical unless they are inside a comparison expression.
3318: The second operand of this function will be non-zero in that case. */
3319:
3320: static void
3321: write_test_expr (exp, in_comparison)
3322: rtx exp;
3323: int in_comparison;
3324: {
3325: int comparison_operator = 0;
3326: RTX_CODE code;
3327: struct attr_desc *attr;
3328:
3329: /* In order not to worry about operator precedence, surround our part of
3330: the expression with parentheses. */
3331:
3332: printf ("(");
3333: code = GET_CODE (exp);
3334: switch (code)
3335: {
3336: /* Binary operators. */
3337: case EQ: case NE:
3338: case GE: case GT: case GEU: case GTU:
3339: case LE: case LT: case LEU: case LTU:
3340: comparison_operator = 1;
3341:
3342: case PLUS: case MINUS: case MULT: case DIV: case MOD:
3343: case AND: case IOR: case XOR:
3344: case LSHIFT: case ASHIFT: case LSHIFTRT: case ASHIFTRT:
3345: write_test_expr (XEXP (exp, 0), in_comparison || comparison_operator);
3346: switch (code)
3347: {
3348: case EQ:
3349: printf (" == ");
3350: break;
3351: case NE:
3352: printf (" != ");
3353: break;
3354: case GE:
3355: printf (" >= ");
3356: break;
3357: case GT:
3358: printf (" > ");
3359: break;
3360: case GEU:
3361: printf (" >= (unsigned) ");
3362: break;
3363: case GTU:
3364: printf (" > (unsigned) ");
3365: break;
3366: case LE:
3367: printf (" <= ");
3368: break;
3369: case LT:
3370: printf (" < ");
3371: break;
3372: case LEU:
3373: printf (" <= (unsigned) ");
3374: break;
3375: case LTU:
3376: printf (" < (unsigned) ");
3377: break;
3378: case PLUS:
3379: printf (" + ");
3380: break;
3381: case MINUS:
3382: printf (" - ");
3383: break;
3384: case MULT:
3385: printf (" * ");
3386: break;
3387: case DIV:
3388: printf (" / ");
3389: break;
3390: case MOD:
1.1.1.2 root 3391: printf (" %% ");
1.1 root 3392: break;
3393: case AND:
3394: if (in_comparison)
3395: printf (" & ");
3396: else
3397: printf (" && ");
3398: break;
3399: case IOR:
3400: if (in_comparison)
3401: printf (" | ");
3402: else
3403: printf (" || ");
3404: break;
3405: case XOR:
3406: printf (" ^ ");
3407: break;
3408: case LSHIFT:
3409: case ASHIFT:
3410: printf (" << ");
3411: break;
3412: case LSHIFTRT:
3413: case ASHIFTRT:
3414: printf (" >> ");
3415: break;
3416: }
3417:
3418: write_test_expr (XEXP (exp, 1), in_comparison || comparison_operator);
3419: break;
3420:
3421: case NOT:
3422: /* Special-case (not (eq_attrq "alternative" "x")) */
3423: if (! in_comparison && GET_CODE (XEXP (exp, 0)) == EQ_ATTR
3424: && XSTR (XEXP (exp, 0), 0) == alternative_name)
3425: {
3426: printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1));
3427: break;
3428: }
3429:
3430: /* Otherwise, fall through to normal unary operator. */
3431:
3432: /* Unary operators. */
3433: case ABS: case NEG:
3434: switch (code)
3435: {
3436: case NOT:
3437: if (in_comparison)
3438: printf ("~ ");
3439: else
3440: printf ("! ");
3441: break;
3442: case ABS:
3443: printf ("abs ");
3444: break;
3445: case NEG:
3446: printf ("-");
3447: break;
3448: }
3449:
3450: write_test_expr (XEXP (exp, 0), in_comparison);
3451: break;
3452:
3453: /* Comparison test of an attribute with a value. Most of these will
3454: have been removed by optimization. Handle "alternative"
3455: specially and give error if EQ_ATTR present inside a comparison. */
3456: case EQ_ATTR:
3457: if (in_comparison)
3458: fatal ("EQ_ATTR not valid inside comparison");
3459:
3460: if (XSTR (exp, 0) == alternative_name)
3461: {
3462: printf ("which_alternative == %s", XSTR (exp, 1));
3463: break;
3464: }
3465:
3466: attr = find_attr (XSTR (exp, 0), 0);
3467: if (! attr) abort ();
1.1.1.3 ! root 3468:
! 3469: /* Now is the time to expand the value of a constant attribute. */
! 3470: if (attr->is_const)
! 3471: {
! 3472: write_test_expr (evaluate_eq_attr (exp, attr->default_val->value,
! 3473: 0, 0),
! 3474: in_comparison);
! 3475: }
! 3476: else
! 3477: {
! 3478: printf ("get_attr_%s (insn) == ", attr->name);
! 3479: write_attr_valueq (attr, XSTR (exp, 1));
! 3480: }
1.1 root 3481: break;
3482:
3483: /* See if an operand matches a predicate. */
3484: case MATCH_OPERAND:
3485: /* If only a mode is given, just ensure the mode matches the operand.
3486: If neither a mode nor predicate is given, error. */
3487: if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0')
3488: {
3489: if (GET_MODE (exp) == VOIDmode)
3490: fatal ("Null MATCH_OPERAND specified as test");
3491: else
3492: printf ("GET_MODE (operands[%d]) == %smode",
3493: XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
3494: }
3495: else
3496: printf ("%s (operands[%d], %smode)",
3497: XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp)));
3498: break;
3499:
3500: /* Constant integer. */
3501: case CONST_INT:
3502: printf ("%d", XINT (exp, 0));
3503: break;
3504:
3505: /* A random C expression. */
3506: case SYMBOL_REF:
3507: printf ("%s", XSTR (exp, 0));
3508: break;
3509:
3510: /* The address of the branch target. */
3511: case MATCH_DUP:
3512: printf ("insn_addresses[INSN_UID (JUMP_LABEL (insn))]");
3513: break;
3514:
3515: /* The address of the current insn. It would be more consistent with
3516: other usage to make this the address of the NEXT insn, but this gets
3517: too confusing because of the ambiguity regarding the length of the
3518: current insn. */
3519: case PC:
3520: printf ("insn_current_address");
3521: break;
3522:
3523: default:
3524: fatal ("bad RTX code `%s' in attribute calculation\n",
3525: GET_RTX_NAME (code));
3526: }
3527:
3528: printf (")");
3529: }
3530:
3531: /* Given an attribute value, return the maximum CONST_STRING argument
3532: encountered. It is assumed that they are all numeric. */
3533:
3534: static int
3535: max_attr_value (exp)
3536: rtx exp;
3537: {
3538: int current_max = 0;
3539: int n;
3540: int i;
3541:
3542: if (GET_CODE (exp) == CONST_STRING)
3543: return atoi (XSTR (exp, 0));
3544:
3545: else if (GET_CODE (exp) == COND)
3546: {
3547: for (i = 0; i < XVECLEN (exp, 0); i += 2)
3548: {
3549: n = max_attr_value (XVECEXP (exp, 0, i + 1));
3550: if (n > current_max)
3551: current_max = n;
3552: }
3553:
3554: n = max_attr_value (XEXP (exp, 1));
3555: if (n > current_max)
3556: current_max = n;
3557: }
3558:
3559: else
3560: abort ();
3561:
3562: return current_max;
3563: }
3564:
3565: /* Scan an attribute value, possibly a conditional, and record what actions
3566: will be required to do any conditional tests in it.
3567:
3568: Specifically, set
3569: `must_extract' if we need to extract the insn operands
3570: `must_constrain' if we must compute `which_alternative'
3571: `address_used' if an address expression was used
3572: */
3573:
3574: static void
3575: walk_attr_value (exp)
3576: rtx exp;
3577: {
3578: register int i, j;
3579: register char *fmt;
3580: RTX_CODE code;
3581:
3582: if (exp == NULL)
3583: return;
3584:
3585: code = GET_CODE (exp);
3586: switch (code)
3587: {
3588: case SYMBOL_REF:
1.1.1.2 root 3589: if (! RTX_UNCHANGING_P (exp))
3590: /* Since this is an arbitrary expression, it can look at anything.
3591: However, constant expressions do not depend on any particular
3592: insn. */
3593: must_extract = must_constrain = 1;
1.1 root 3594: return;
3595:
3596: case MATCH_OPERAND:
3597: must_extract = 1;
3598: return;
3599:
3600: case EQ_ATTR:
3601: if (XSTR (exp, 0) == alternative_name)
3602: must_extract = must_constrain = 1;
3603: return;
3604:
3605: case MATCH_DUP:
3606: case PC:
3607: address_used = 1;
3608: return;
3609: }
3610:
3611: for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++)
3612: switch (*fmt++)
3613: {
3614: case 'e':
3615: case 'u':
3616: walk_attr_value (XEXP (exp, i));
3617: break;
3618:
3619: case 'E':
3620: if (XVEC (exp, i) != NULL)
3621: for (j = 0; j < XVECLEN (exp, i); j++)
3622: walk_attr_value (XVECEXP (exp, i, j));
3623: break;
3624: }
3625: }
3626:
3627: /* Write out a function to obtain the attribute for a given INSN. */
3628:
3629: static void
3630: write_attr_get (attr)
3631: struct attr_desc *attr;
3632: {
3633: struct attr_value *av, *common_av;
3634:
3635: /* Find the most used attribute value. Handle that as the `default' of the
3636: switch we will generate. */
3637: common_av = find_most_used (attr);
3638:
3639: /* Write out start of function, then all values with explicit `case' lines,
3640: then a `default', then the value with the most uses. */
3641: if (attr->is_numeric)
3642: printf ("int\n");
3643: else
3644: printf ("enum attr_%s\n", attr->name);
3645:
3646: /* If the attribute name starts with a star, the remainder is the name of
3647: the subroutine to use, instead of `get_attr_...'. */
3648: if (attr->name[0] == '*')
3649: printf ("%s (insn)\n", &attr->name[1]);
1.1.1.2 root 3650: else if (attr->is_const == 0)
1.1 root 3651: printf ("get_attr_%s (insn)\n", attr->name);
1.1.1.2 root 3652: else
3653: {
3654: printf ("get_attr_%s ()\n", attr->name);
3655: printf ("{\n");
3656:
3657: for (av = attr->first_value; av; av = av->next)
3658: if (av->num_insns != 0)
3659: write_attr_set (attr, 2, av->value, "return", ";",
3660: true_rtx, av->first_insn->insn_code,
3661: av->first_insn->insn_index);
3662:
3663: printf ("}\n\n");
3664: return;
3665: }
1.1 root 3666: printf (" rtx insn;\n");
3667: printf ("{\n");
3668: printf (" switch (recog_memoized (insn))\n");
3669: printf (" {\n");
3670:
3671: for (av = attr->first_value; av; av = av->next)
3672: if (av != common_av)
3673: write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
3674:
3675: write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
3676: printf (" }\n}\n\n");
3677: }
3678:
3679: /* Given an AND tree of known true terms (because we are inside an `if' with
3680: that as the condition or are in an `else' clause) and an expression,
3681: replace any known true terms with TRUE. Use `simplify_and_tree' to do
3682: the bulk of the work. */
3683:
3684: static rtx
3685: eliminate_known_true (known_true, exp, insn_code, insn_index)
3686: rtx known_true;
3687: rtx exp;
3688: int insn_code, insn_index;
3689: {
3690: rtx term;
3691:
3692: known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index);
3693:
3694: if (GET_CODE (known_true) == AND)
3695: {
3696: exp = eliminate_known_true (XEXP (known_true, 0), exp,
3697: insn_code, insn_index);
3698: exp = eliminate_known_true (XEXP (known_true, 1), exp,
3699: insn_code, insn_index);
3700: }
3701: else
3702: {
3703: term = known_true;
3704: exp = simplify_and_tree (exp, &term, insn_code, insn_index);
3705: }
3706:
3707: return exp;
3708: }
3709:
3710: /* Write out a series of tests and assignment statements to perform tests and
3711: sets of an attribute value. We are passed an indentation amount and prefix
3712: and suffix strings to write around each attribute value (e.g., "return"
3713: and ";"). */
3714:
3715: static void
3716: write_attr_set (attr, indent, value, prefix, suffix, known_true,
3717: insn_code, insn_index)
3718: struct attr_desc *attr;
3719: int indent;
3720: rtx value;
3721: char *prefix;
3722: char *suffix;
3723: rtx known_true;
3724: int insn_code, insn_index;
3725: {
3726: if (GET_CODE (value) == CONST_STRING)
3727: {
3728: write_indent (indent);
3729: printf ("%s ", prefix);
3730: write_attr_value (attr, value);
3731: printf ("%s\n", suffix);
3732: }
3733: else if (GET_CODE (value) == COND)
3734: {
3735: /* Assume the default value will be the default of the COND unless we
3736: find an always true expression. */
3737: rtx default_val = XEXP (value, 1);
3738: rtx our_known_true = known_true;
3739: rtx newexp;
3740: int first_if = 1;
3741: int i;
3742:
3743: for (i = 0; i < XVECLEN (value, 0); i += 2)
3744: {
3745: rtx testexp;
3746: rtx inner_true;
3747:
3748: testexp = eliminate_known_true (our_known_true,
3749: XVECEXP (value, 0, i),
3750: insn_code, insn_index);
1.1.1.2 root 3751: newexp = attr_rtx (NOT, testexp);
1.1 root 3752: newexp = insert_right_side (AND, our_known_true, newexp,
3753: insn_code, insn_index);
3754:
3755: /* If the test expression is always true or if the next `known_true'
3756: expression is always false, this is the last case, so break
3757: out and let this value be the `else' case. */
3758: if (testexp == true_rtx || newexp == false_rtx)
3759: {
3760: default_val = XVECEXP (value, 0, i + 1);
3761: break;
3762: }
3763:
3764: /* Compute the expression to pass to our recursive call as being
3765: known true. */
3766: inner_true = insert_right_side (AND, our_known_true,
3767: testexp, insn_code, insn_index);
3768:
3769: /* If this is always false, skip it. */
3770: if (inner_true == false_rtx)
3771: continue;
3772:
3773: write_indent (indent);
3774: printf ("%sif ", first_if ? "" : "else ");
3775: first_if = 0;
3776: write_test_expr (testexp, 0);
3777: printf ("\n");
3778: write_indent (indent + 2);
3779: printf ("{\n");
3780:
3781: write_attr_set (attr, indent + 4,
3782: XVECEXP (value, 0, i + 1), prefix, suffix,
3783: inner_true, insn_code, insn_index);
3784: write_indent (indent + 2);
3785: printf ("}\n");
3786: our_known_true = newexp;
3787: }
3788:
3789: if (! first_if)
3790: {
3791: write_indent (indent);
3792: printf ("else\n");
3793: write_indent (indent + 2);
3794: printf ("{\n");
3795: }
3796:
3797: write_attr_set (attr, first_if ? indent : indent + 4, default_val,
3798: prefix, suffix, our_known_true, insn_code, insn_index);
3799:
3800: if (! first_if)
3801: {
3802: write_indent (indent + 2);
3803: printf ("}\n");
3804: }
3805: }
3806: else
3807: abort ();
3808: }
3809:
3810: /* Write out the computation for one attribute value. */
3811:
3812: static void
3813: write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, known_true)
3814: struct attr_desc *attr;
3815: struct attr_value *av;
3816: int write_case_lines;
3817: char *prefix, *suffix;
3818: int indent;
3819: rtx known_true;
3820: {
3821: struct insn_ent *ie;
3822:
3823: if (av->num_insns == 0)
3824: return;
3825:
3826: if (av->has_asm_insn)
3827: {
3828: write_indent (indent);
3829: printf ("case -1:\n");
3830: write_indent (indent + 2);
3831: printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n");
3832: write_indent (indent + 2);
3833: printf (" && asm_noperands (PATTERN (insn)) < 0)\n");
3834: write_indent (indent + 2);
3835: printf (" fatal_insn_not_found (insn);\n");
3836: }
3837:
3838: if (write_case_lines)
3839: {
3840: for (ie = av->first_insn; ie; ie = ie->next)
3841: if (ie->insn_code != -1)
3842: {
3843: write_indent (indent);
3844: printf ("case %d:\n", ie->insn_code);
3845: }
3846: }
3847: else
3848: {
3849: write_indent (indent);
3850: printf ("default:\n");
3851: }
3852:
3853: /* See what we have to do to handle output this value. */
3854: must_extract = must_constrain = address_used = 0;
3855: walk_attr_value (av->value);
3856:
3857: if (must_extract)
3858: {
3859: write_indent (indent + 2);
3860: printf ("insn_extract (insn);\n");
3861: }
3862:
3863: if (must_constrain)
3864: {
3865: #ifdef REGISTER_CONSTRAINTS
3866: write_indent (indent + 2);
3867: printf ("if (! constrain_operands (INSN_CODE (insn), reload_completed))\n");
3868: write_indent (indent + 2);
3869: printf (" fatal_insn_not_found (insn);\n");
3870: #endif
3871: }
3872:
3873: write_attr_set (attr, indent + 2, av->value, prefix, suffix,
3874: known_true, av->first_insn->insn_code,
3875: av->first_insn->insn_index);
3876:
3877: if (strncmp (prefix, "return", 6))
3878: {
3879: write_indent (indent + 2);
3880: printf ("break;\n");
3881: }
3882: printf ("\n");
3883: }
3884:
3885: /* Utilities to write names in various forms. */
3886:
3887: static void
3888: write_attr_valueq (attr, s)
3889: struct attr_desc *attr;
3890: char *s;
3891: {
3892: if (attr->is_numeric)
3893: printf ("%s", s);
3894: else
3895: {
3896: write_upcase (attr->name);
3897: printf ("_");
3898: write_upcase (s);
3899: }
3900: }
3901:
3902: static void
3903: write_attr_value (attr, value)
3904: struct attr_desc *attr;
3905: rtx value;
3906: {
3907: if (GET_CODE (value) != CONST_STRING)
3908: abort ();
3909:
3910: write_attr_valueq (attr, XSTR (value, 0));
3911: }
3912:
3913: static void
3914: write_upcase (str)
3915: char *str;
3916: {
3917: while (*str)
3918: if (*str < 'a' || *str > 'z')
3919: printf ("%c", *str++);
3920: else
3921: printf ("%c", *str++ - 'a' + 'A');
3922: }
3923:
3924: static void
3925: write_indent (indent)
3926: int indent;
3927: {
3928: for (; indent > 8; indent -= 8)
3929: printf ("\t");
3930:
3931: for (; indent; indent--)
3932: printf (" ");
3933: }
3934:
3935: /* Write a subroutine that is given an insn that requires a delay slot, a
3936: delay slot ordinal, and a candidate insn. It returns non-zero if the
3937: candidate can be placed in the specified delay slot of the insn.
3938:
3939: We can write as many as three subroutines. `eligible_for_delay'
3940: handles normal delay slots, `eligible_for_annul_true' indicates that
3941: the specified insn can be annulled if the branch is true, and likewise
3942: for `eligible_for_annul_false'.
3943:
1.1.1.3 ! root 3944: KIND is a string distinguishing these three cases ("delay", "annul_true",
1.1 root 3945: or "annul_false"). */
3946:
3947: static void
3948: write_eligible_delay (kind)
3949: char *kind;
3950: {
3951: struct delay_desc *delay;
3952: int max_slots;
3953: char str[50];
3954: struct attr_desc *attr;
3955: struct attr_value *av, *common_av;
3956: int i;
3957:
3958: /* Compute the maximum number of delay slots required. We use the delay
3959: ordinal times this number plus one, plus the slot number as an index into
3960: the appropriate predicate to test. */
3961:
3962: for (delay = delays, max_slots = 0; delay; delay = delay->next)
3963: if (XVECLEN (delay->def, 1) / 3 > max_slots)
3964: max_slots = XVECLEN (delay->def, 1) / 3;
3965:
3966: /* Write function prelude. */
3967:
3968: printf ("int\n");
3969: printf ("eligible_for_%s (delay_insn, slot, candidate_insn)\n", kind);
3970: printf (" rtx delay_insn;\n");
3971: printf (" int slot;\n");
3972: printf (" rtx candidate_insn;\n");
3973: printf ("{\n");
3974: printf (" rtx insn;\n");
3975: printf ("\n");
3976: printf (" if (slot >= %d)\n", max_slots);
3977: printf (" abort ();\n");
3978: printf ("\n");
3979:
3980: /* If more than one delay type, find out which type the delay insn is. */
3981:
3982: if (num_delays > 1)
3983: {
1.1.1.2 root 3984: attr = find_attr ("*delay_type", 0);
1.1 root 3985: if (! attr) abort ();
3986: common_av = find_most_used (attr);
3987:
3988: printf (" insn = delay_insn;\n");
3989: printf (" switch (recog_memoized (insn))\n");
3990: printf (" {\n");
3991:
3992: sprintf (str, " * %d;\n break;", max_slots);
3993: for (av = attr->first_value; av; av = av->next)
3994: if (av != common_av)
3995: write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx);
3996:
3997: write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx);
3998: printf (" }\n\n");
3999:
4000: /* Ensure matched. Otherwise, shouldn't have been called. */
4001: printf (" if (slot < %d)\n", max_slots);
4002: printf (" abort ();\n\n");
4003: }
4004:
4005: /* If just one type of delay slot, write simple switch. */
4006: if (num_delays == 1 && max_slots == 1)
4007: {
4008: printf (" insn = candidate_insn;\n");
4009: printf (" switch (recog_memoized (insn))\n");
4010: printf (" {\n");
4011:
4012: attr = find_attr ("*delay_1_0", 0);
4013: if (! attr) abort ();
4014: common_av = find_most_used (attr);
4015:
4016: for (av = attr->first_value; av; av = av->next)
4017: if (av != common_av)
4018: write_attr_case (attr, av, 1, "return", ";", 4, true_rtx);
4019:
4020: write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx);
4021: printf (" }\n");
4022: }
4023:
4024: else
4025: {
4026: /* Write a nested CASE. The first indicates which condition we need to
4027: test, and the inner CASE tests the condition. */
4028: printf (" insn = candidate_insn;\n");
4029: printf (" switch (slot)\n");
4030: printf (" {\n");
4031:
4032: for (delay = delays; delay; delay = delay->next)
4033: for (i = 0; i < XVECLEN (delay->def, 1); i += 3)
4034: {
4035: printf (" case %d:\n",
4036: (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots));
4037: printf (" switch (recog_memoized (insn))\n");
4038: printf ("\t{\n");
4039:
4040: sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3);
4041: attr = find_attr (str, 0);
4042: if (! attr) abort ();
4043: common_av = find_most_used (attr);
4044:
4045: for (av = attr->first_value; av; av = av->next)
4046: if (av != common_av)
4047: write_attr_case (attr, av, 1, "return", ";", 8, true_rtx);
4048:
4049: write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx);
4050: printf (" }\n");
4051: }
4052:
4053: printf (" default:\n");
4054: printf (" abort ();\n");
4055: printf (" }\n");
4056: }
4057:
4058: printf ("}\n\n");
4059: }
4060:
4061: /* Write routines to compute conflict cost for function units. Then write a
4062: table describing the available function units. */
4063:
4064: static void
4065: write_function_unit_info ()
4066: {
4067: struct function_unit *unit;
4068: struct attr_desc *case_attr, *attr;
4069: struct attr_value *av, *common_av;
4070: rtx value;
4071: char *str;
4072: int using_case;
4073: int i;
4074:
4075: /* Write out conflict routines for function units. Don't bother writing
4076: one if there is only one busy value. */
4077:
4078: for (unit = units; unit; unit = unit->next)
4079: {
4080: /* See if only one case exists and if there is a constant value for
4081: that case. If so, we don't need a function. */
1.1.1.2 root 4082: str = (char *) alloca (strlen (unit->name) + 10);
1.1 root 4083: sprintf (str, "*%s_cases", unit->name);
4084: attr = find_attr (str, 0);
4085: if (! attr) abort ();
4086: value = find_single_value (attr);
4087: if (value && GET_CODE (value) == CONST_STRING)
4088: {
4089: sprintf (str, "*%s_case_%s", unit->name, XSTR (value, 0));
4090: attr = find_attr (str, 0);
4091: if (! attr) abort ();
4092: value = find_single_value (attr);
4093: if (value && GET_CODE (value) == CONST_STRING)
4094: {
4095: unit->needs_conflict_function = 0;
4096: unit->default_cost = value;
4097: continue;
4098: }
4099: }
4100:
4101: /* The function first computes the case from the candidate insn. */
4102: unit->needs_conflict_function = 1;
4103: unit->default_cost = make_numeric_value (0);
4104:
4105: printf ("static int\n");
4106: printf ("%s_unit_conflict_cost (executing_insn, candidate_insn)\n",
4107: unit->name);
4108: printf (" rtx executing_insn;\n");
4109: printf (" rtx candidate_insn;\n");
4110: printf ("{\n");
4111: printf (" rtx insn;\n");
4112: printf (" int casenum;\n\n");
4113: printf (" insn = candidate_insn;\n");
4114: printf (" switch (recog_memoized (insn))\n");
4115: printf (" {\n");
4116:
4117: /* Write the `switch' statement to get the case value. */
4118: sprintf (str, "*%s_cases", unit->name);
4119: case_attr = find_attr (str, 0);
4120: if (! case_attr) abort ();
4121: common_av = find_most_used (case_attr);
4122:
4123: for (av = case_attr->first_value; av; av = av->next)
4124: if (av != common_av)
4125: write_attr_case (case_attr, av, 1,
4126: "casenum =", ";", 4, unit->condexp);
4127:
4128: write_attr_case (case_attr, common_av, 0,
4129: "casenum =", ";", 4, unit->condexp);
4130: printf (" }\n\n");
4131:
4132: /* Now write an outer switch statement on each case. Then write
4133: the tests on the executing function within each. */
4134: printf (" insn = executing_insn;\n");
4135: printf (" switch (casenum)\n");
4136: printf (" {\n");
4137:
4138: for (i = 0; i < unit->num_opclasses; i++)
4139: {
4140: /* Ensure using this case. */
4141: using_case = 0;
4142: for (av = case_attr->first_value; av; av = av->next)
4143: if (av->num_insns
4144: && contained_in_p (make_numeric_value (i), av->value))
4145: using_case = 1;
4146:
4147: if (! using_case)
4148: continue;
4149:
4150: printf (" case %d:\n", i);
4151: sprintf (str, "*%s_case_%d", unit->name, i);
4152: attr = find_attr (str, 0);
4153: if (! attr) abort ();
4154:
4155: /* If single value, just write it. */
4156: value = find_single_value (attr);
4157: if (value)
4158: write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2);
4159: else
4160: {
4161: common_av = find_most_used (attr);
4162: printf (" switch (recog_memoized (insn))\n");
4163: printf ("\t{\n");
4164:
4165: for (av = attr->first_value; av; av = av->next)
4166: if (av != common_av)
4167: write_attr_case (attr, av, 1,
4168: "return", ";", 8, unit->condexp);
4169:
4170: write_attr_case (attr, common_av, 0,
4171: "return", ";", 8, unit->condexp);
4172: printf (" }\n\n");
4173: }
4174: }
4175:
4176: printf (" }\n}\n\n");
4177: }
4178:
4179: /* Now that all functions have been written, write the table describing
1.1.1.3 ! root 4180: the function units. The name is included for documentation purposes
1.1 root 4181: only. */
4182:
4183: printf ("struct function_unit_desc function_units[] = {\n");
4184:
4185: for (unit = units; unit; unit = unit->next)
4186: {
4187: printf (" {\"%s\", %d, %d, %d, %s, %s_unit_ready_cost, ",
4188: unit->name, 1 << unit->num, unit->multiplicity,
4189: unit->simultaneity, XSTR (unit->default_cost, 0), unit->name);
4190:
4191: if (unit->needs_conflict_function)
4192: printf ("%s_unit_conflict_cost", unit->name);
4193: else
4194: printf ("0");
4195:
4196: printf ("}, \n");
4197: }
4198:
4199: printf ("};\n\n");
4200: }
4201:
4202: /* This page contains miscellaneous utility routines. */
4203:
4204: /* Given a string, return the number of comma-separated elements in it.
4205: Return 0 for the null string. */
4206:
4207: static int
4208: n_comma_elts (s)
4209: char *s;
4210: {
4211: int n;
4212:
4213: if (*s == '\0')
4214: return 0;
4215:
4216: for (n = 1; *s; s++)
4217: if (*s == ',')
4218: n++;
4219:
4220: return n;
4221: }
4222:
4223: /* Given a pointer to a (char *), return a malloc'ed string containing the
4224: next comma-separated element. Advance the pointer to after the string
4225: scanned, or the end-of-string. Return NULL if at end of string. */
4226:
4227: static char *
4228: next_comma_elt (pstr)
4229: char **pstr;
4230: {
4231: char *out_str;
4232: char *p;
4233:
4234: if (**pstr == '\0')
4235: return NULL;
4236:
4237: /* Find end of string to compute length. */
4238: for (p = *pstr; *p != ',' && *p != '\0'; p++)
4239: ;
4240:
1.1.1.2 root 4241: out_str = attr_string (*pstr, p - *pstr);
4242: *pstr = p;
1.1 root 4243:
4244: if (**pstr == ',')
4245: (*pstr)++;
4246:
4247: return out_str;
4248: }
4249:
4250: /* Return a `struct attr_desc' pointer for a given named attribute. If CREATE
4251: is non-zero, build a new attribute, if one does not exist. */
4252:
4253: static struct attr_desc *
4254: find_attr (name, create)
4255: char *name;
4256: int create;
4257: {
4258: struct attr_desc *attr;
1.1.1.3 ! root 4259: int index;
1.1 root 4260:
4261: /* Before we resort to using `strcmp', see if the string address matches
4262: anywhere. In most cases, it should have been canonicalized to do so. */
4263: if (name == alternative_name)
4264: return NULL;
4265:
1.1.1.3 ! root 4266: index = name[0] & (MAX_ATTRS_INDEX - 1);
! 4267: for (attr = attrs[index]; attr; attr = attr->next)
1.1 root 4268: if (name == attr->name)
4269: return attr;
4270:
4271: /* Otherwise, do it the slow way. */
1.1.1.3 ! root 4272: for (attr = attrs[index]; attr; attr = attr->next)
! 4273: if (name[0] == attr->name[0] && ! strcmp (name, attr->name))
1.1 root 4274: return attr;
4275:
4276: if (! create)
4277: return NULL;
4278:
4279: attr = (struct attr_desc *) xmalloc (sizeof (struct attr_desc));
1.1.1.3 ! root 4280: attr->name = attr_string (name, strlen (name));
1.1 root 4281: attr->first_value = attr->default_val = NULL;
1.1.1.2 root 4282: attr->is_numeric = attr->is_const = attr->is_special = 0;
1.1.1.3 ! root 4283: attr->next = attrs[index];
! 4284: attrs[index] = attr;
1.1 root 4285:
4286: return attr;
4287: }
4288:
4289: /* Create internal attribute with the given default value. */
4290:
4291: static void
4292: make_internal_attr (name, value, special)
4293: char *name;
4294: rtx value;
4295: int special;
4296: {
4297: struct attr_desc *attr;
4298:
4299: attr = find_attr (name, 1);
4300: if (attr->default_val)
4301: abort ();
4302:
4303: attr->is_numeric = 1;
1.1.1.2 root 4304: attr->is_const = 0;
1.1 root 4305: attr->is_special = special;
4306: attr->default_val = get_attr_value (value, attr, -2);
4307: }
4308:
4309: /* Find the most used value of an attribute. */
4310:
4311: static struct attr_value *
4312: find_most_used (attr)
4313: struct attr_desc *attr;
4314: {
4315: struct attr_value *av;
4316: struct attr_value *most_used;
4317: int nuses;
4318:
4319: most_used = NULL;
4320: nuses = -1;
4321:
4322: for (av = attr->first_value; av; av = av->next)
4323: if (av->num_insns > nuses)
4324: nuses = av->num_insns, most_used = av;
4325:
4326: return most_used;
4327: }
4328:
4329: /* If an attribute only has a single value used, return it. Otherwise
4330: return NULL. */
4331:
4332: static rtx
4333: find_single_value (attr)
4334: struct attr_desc *attr;
4335: {
4336: struct attr_value *av;
4337: rtx unique_value;
4338:
4339: unique_value = NULL;
4340: for (av = attr->first_value; av; av = av->next)
4341: if (av->num_insns)
4342: {
4343: if (unique_value)
4344: return NULL;
4345: else
4346: unique_value = av->value;
4347: }
4348:
4349: return unique_value;
4350: }
4351:
4352: /* Return (attr_value "n") */
4353:
4354: static rtx
4355: make_numeric_value (n)
4356: int n;
4357: {
4358: static rtx int_values[20];
4359: rtx exp;
1.1.1.2 root 4360: char *p;
1.1 root 4361:
4362: if (n < 0)
4363: abort ();
4364:
4365: if (n < 20 && int_values[n])
4366: return int_values[n];
4367:
1.1.1.2 root 4368: p = attr_printf ((n < 1000 ? 4 : HOST_BITS_PER_INT * 3 / 10 + 3), "%d", n);
4369: exp = attr_rtx (CONST_STRING, p);
1.1 root 4370:
4371: if (n < 20)
4372: int_values[n] = exp;
4373:
4374: return exp;
4375: }
4376:
4377: char *
4378: xrealloc (ptr, size)
4379: char *ptr;
4380: unsigned size;
4381: {
4382: char *result = (char *) realloc (ptr, size);
4383: if (!result)
4384: fatal ("virtual memory exhausted");
4385: return result;
4386: }
4387:
4388: char *
4389: xmalloc (size)
4390: unsigned size;
4391: {
4392: register char *val = (char *) malloc (size);
4393:
4394: if (val == 0)
4395: fatal ("virtual memory exhausted");
4396: return val;
4397: }
4398:
1.1.1.3 ! root 4399: static rtx
! 4400: copy_rtx_unchanging (orig)
! 4401: register rtx orig;
! 4402: {
! 4403: register rtx copy;
! 4404: register RTX_CODE code;
! 4405:
! 4406: if (RTX_UNCHANGING_P (orig) || MEM_IN_STRUCT_P (orig))
! 4407: return orig;
! 4408:
! 4409: MEM_IN_STRUCT_P (orig) = 1;
! 4410: return orig;
! 4411:
! 4412: #if 0
! 4413: code = GET_CODE (orig);
! 4414: switch (code)
! 4415: {
! 4416: case CONST_INT:
! 4417: case CONST_DOUBLE:
! 4418: case SYMBOL_REF:
! 4419: case CODE_LABEL:
! 4420: return orig;
! 4421: }
! 4422:
! 4423: copy = rtx_alloc (code);
! 4424: PUT_MODE (copy, GET_MODE (orig));
! 4425: RTX_UNCHANGING_P (copy) = 1;
! 4426:
! 4427: bcopy (&XEXP (orig, 0), &XEXP (copy, 0),
! 4428: GET_RTX_LENGTH (GET_CODE (copy)) * sizeof (rtx));
! 4429: return copy;
! 4430: #endif
! 4431: }
! 4432:
1.1 root 4433: static void
4434: fatal (s, a1, a2)
4435: char *s;
4436: {
4437: fprintf (stderr, "genattrtab: ");
4438: fprintf (stderr, s, a1, a2);
4439: fprintf (stderr, "\n");
4440: exit (FATAL_EXIT_CODE);
4441: }
4442:
4443: /* More 'friendly' abort that prints the line and file.
4444: config.h can #define abort fancy_abort if you like that sort of thing. */
4445:
4446: void
4447: fancy_abort ()
4448: {
4449: fatal ("Internal gcc abort.");
4450: }
4451:
4452: int
4453: main (argc, argv)
4454: int argc;
4455: char **argv;
4456: {
4457: rtx desc;
4458: FILE *infile;
4459: register int c;
4460: struct attr_desc *attr;
4461: struct attr_value *av;
4462: struct insn_def *id;
4463: rtx tem;
1.1.1.3 ! root 4464: int i;
1.1 root 4465:
4466: obstack_init (rtl_obstack);
1.1.1.3 ! root 4467: obstack_init (hash_obstack);
! 4468: obstack_init (temp_obstack);
1.1 root 4469:
4470: if (argc <= 1)
4471: fatal ("No input file name.");
4472:
4473: infile = fopen (argv[1], "r");
4474: if (infile == 0)
4475: {
4476: perror (argv[1]);
4477: exit (FATAL_EXIT_CODE);
4478: }
4479:
4480: init_rtl ();
4481:
4482: /* Set up true and false rtx's */
1.1.1.3 ! root 4483: true_rtx = rtx_alloc (CONST_INT);
! 4484: XINT (true_rtx, 0) = 1;
! 4485: false_rtx = rtx_alloc (CONST_INT);
! 4486: XINT (false_rtx, 0) = 0;
1.1 root 4487: RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1;
1.1.1.3 ! root 4488: RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1;
! 4489:
! 4490: alternative_name = attr_string ("alternative", strlen ("alternative"));
1.1 root 4491:
4492: printf ("/* Generated automatically by the program `genattrtab'\n\
4493: from the machine description file `md'. */\n\n");
4494:
4495: /* Read the machine description. */
4496:
4497: while (1)
4498: {
4499: c = read_skip_spaces (infile);
4500: if (c == EOF)
4501: break;
4502: ungetc (c, infile);
4503:
4504: desc = read_rtx (infile);
4505: if (GET_CODE (desc) == DEFINE_INSN
4506: || GET_CODE (desc) == DEFINE_PEEPHOLE
4507: || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES)
4508: gen_insn (desc);
4509:
4510: else if (GET_CODE (desc) == DEFINE_EXPAND)
4511: insn_code_number++, insn_index_number++;
4512:
4513: else if (GET_CODE (desc) == DEFINE_SPLIT)
4514: insn_code_number++, insn_index_number++;
4515:
4516: else if (GET_CODE (desc) == DEFINE_ATTR)
4517: {
4518: gen_attr (desc);
4519: insn_index_number++;
4520: }
4521:
4522: else if (GET_CODE (desc) == DEFINE_DELAY)
4523: {
4524: gen_delay (desc);
4525: insn_index_number++;
4526: }
4527:
4528: else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT)
4529: {
4530: gen_unit (desc);
4531: insn_index_number++;
4532: }
4533: }
4534:
4535: /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one. */
4536: if (! got_define_asm_attributes)
4537: {
4538: tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES);
4539: XVEC (tem, 0) = rtvec_alloc (0);
4540: gen_insn (tem);
4541: }
4542:
4543: /* Expand DEFINE_DELAY information into new attribute. */
4544: if (num_delays)
4545: expand_delays ();
4546:
4547: /* Expand DEFINE_FUNCTION_UNIT information into new attributes. */
4548: if (num_units)
4549: expand_units ();
4550:
4551: printf ("#include \"config.h\"\n");
4552: printf ("#include \"rtl.h\"\n");
4553: printf ("#include \"insn-config.h\"\n");
4554: printf ("#include \"recog.h\"\n");
4555: printf ("#include \"regs.h\"\n");
4556: printf ("#include \"real.h\"\n");
4557: printf ("#include \"output.h\"\n");
4558: printf ("#include \"insn-attr.h\"\n");
4559: printf ("\n");
4560: printf ("#define operands recog_operand\n\n");
4561:
4562: /* Make `insn_alternatives'. */
4563: insn_alternatives = (int *) xmalloc (insn_code_number * sizeof (int));
4564: for (id = defs; id; id = id->next)
4565: if (id->insn_code >= 0)
4566: insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1;
4567:
1.1.1.3 ! root 4568: /* Make `insn_n_alternatives'. */
! 4569: insn_n_alternatives = (int *) xmalloc (insn_code_number * sizeof (int));
! 4570: for (id = defs; id; id = id->next)
! 4571: if (id->insn_code >= 0)
! 4572: insn_n_alternatives[id->insn_code] = id->num_alternatives;
! 4573:
1.1 root 4574: /* Prepare to write out attribute subroutines by checking everything stored
4575: away and building the attribute cases. */
4576:
4577: check_defs ();
1.1.1.3 ! root 4578: for (i = 0; i < MAX_ATTRS_INDEX; i++)
! 4579: for (attr = attrs[i]; attr; attr = attr->next)
! 4580: {
! 4581: attr->default_val->value
! 4582: = check_attr_value (attr->default_val->value, attr);
! 4583: fill_attr (attr);
! 4584: }
1.1 root 4585:
4586: /* Construct extra attributes for `length'. */
4587: make_length_attrs ();
4588:
4589: /* Perform any possible optimizations to speed up compilation. */
4590: optimize_attrs ();
4591:
4592: /* Now write out all the `gen_attr_...' routines. Do these before the
4593: special routines (specifically before write_function_unit_info), so
4594: that they get defined before they are used. */
4595:
1.1.1.3 ! root 4596: for (i = 0; i < MAX_ATTRS_INDEX; i++)
! 4597: for (attr = attrs[i]; attr; attr = attr->next)
! 4598: {
! 4599: if (! attr->is_special)
! 4600: write_attr_get (attr);
! 4601: }
1.1 root 4602:
4603: /* Write out delay eligibility information, if DEFINE_DELAY present.
4604: (The function to compute the number of delay slots will be written
4605: below.) */
4606: if (num_delays)
4607: {
4608: write_eligible_delay ("delay");
4609: if (have_annul_true)
4610: write_eligible_delay ("annul_true");
4611: if (have_annul_false)
4612: write_eligible_delay ("annul_false");
4613: }
4614:
4615: /* Write out information about function units. */
4616: if (num_units)
4617: write_function_unit_info ();
4618:
4619: fflush (stdout);
4620: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
4621: /* NOTREACHED */
4622: return 0;
4623: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.