|
|
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.