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