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