|
|
1.1 root 1: /* Generate code from machine description to compute values of attributes. 1.1.1.6 ! root 2: Copyright (C) 1991, 1993 Free Software Foundation, Inc. 1.1 root 3: Contributed by Richard Kenner ([email protected]) 4: 5: This file is part of GNU CC. 6: 7: GNU CC is free software; you can redistribute it and/or modify 8: it under the terms of the GNU General Public License as published by 9: the Free Software Foundation; either version 2, or (at your option) 10: any later version. 11: 12: GNU CC is distributed in the hope that it will be useful, 13: but WITHOUT ANY WARRANTY; without even the implied warranty of 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15: GNU General Public License for more details. 16: 17: You should have received a copy of the GNU General Public License 18: along with GNU CC; see the file COPYING. If not, write to 19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ 20: 1.1.1.3 root 21: /* This program handles insn attributes and the DEFINE_DELAY and 1.1 root 22: DEFINE_FUNCTION_UNIT definitions. 23: 1.1.1.2 root 24: It produces a series of functions named `get_attr_...', one for each insn 1.1 root 25: attribute. Each of these is given the rtx for an insn and returns a member 26: of the enum for the attribute. 27: 28: These subroutines have the form of a `switch' on the INSN_CODE (via 29: `recog_memoized'). Each case either returns a constant attribute value 30: or a value that depends on tests on other attributes, the form of 31: operands, or some random C expression (encoded with a SYMBOL_REF 32: expression). 33: 34: If the attribute `alternative', or a random C expression is present, 35: `constrain_operands' is called. If either of these cases of a reference to 36: an operand is found, `insn_extract' is called. 37: 38: The special attribute `length' is also recognized. For this operand, 39: expressions involving the address of an operand or the current insn, 40: (address (pc)), are valid. In this case, an initial pass is made to 41: set all lengths that do not depend on address. Those that do are set to 42: the maximum length. Then each insn that depends on an address is checked 43: and possibly has its length changed. The process repeats until no further 44: changed are made. The resulting lengths are saved for use by 45: `get_attr_length'. 46: 1.1.1.2 root 47: A special form of DEFINE_ATTR, where the expression for default value is a 48: CONST expression, indicates an attribute that is constant for a given run 49: of the compiler. The subroutine generated for these attributes has no 50: parameters as it does not depend on any particular insn. Constant 51: attributes are typically used to specify which variety of processor is 52: used. 53: 1.1 root 54: Internal attributes are defined to handle DEFINE_DELAY and 55: DEFINE_FUNCTION_UNIT. Special routines are output for these cases. 56: 57: This program works by keeping a list of possible values for each attribute. 58: These include the basic attribute choices, default values for attribute, and 59: all derived quantities. 60: 61: As the description file is read, the definition for each insn is saved in a 62: `struct insn_def'. When the file reading is complete, a `struct insn_ent' 63: is created for each insn and chained to the corresponding attribute value, 64: either that specified, or the default. 65: 66: An optimization phase is then run. This simplifies expressions for each 67: insn. EQ_ATTR tests are resolved, whenever possible, to a test that 68: indicates when the attribute has the specified value for the insn. This 69: avoids recursive calls during compilation. 70: 71: The strategy used when processing DEFINE_DELAY and DEFINE_FUNCTION_UNIT 72: definitions is to create arbitrarily complex expressions and have the 73: optimization simplify them. 74: 75: Once optimization is complete, any required routines and definitions 1.1.1.2 root 76: will be written. 77: 78: An optimization that is not yet implemented is to hoist the constant 79: expressions entirely out of the routines and definitions that are written. 80: A way to do this is to iterate over all possible combinations of values 81: for constant attributes and generate a set of functions for that given 82: combination. An initialization function would be written that evaluates 83: the attributes and installs the corresponding set of routines and 1.1.1.3 root 84: definitions (each would be accessed through a pointer). 85: 86: We use the flags in an RTX as follows: 87: `unchanging' (RTX_UNCHANGING_P): This rtx is fully simplified 88: independent of the insn code. 89: `in_struct' (MEM_IN_STRUCT_P): This rtx is fully simplified 90: for the insn code currently being processed (see optimize_attrs). 91: `integrated' (RTX_INTEGRATED_P): This rtx is permanent and unique 1.1.1.4 root 92: (see attr_rtx). 93: `volatil' (MEM_VOLATILE_P): During simplify_by_exploding the value of an 94: EQ_ATTR rtx is true if !volatil and false if volatil. */ 1.1.1.3 root 95: 1.1 root 96: 1.1.1.4 root 97: #include "hconfig.h" 1.1.1.6 ! root 98: /* gvarargs must always be included after *config.h. */ ! 99: #include "gvarargs.h" 1.1 root 100: #include "rtl.h" 101: #include "insn-config.h" /* For REGISTER_CONSTRAINTS */ 1.1.1.4 root 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" 1.1 root 114: 1.1.1.3 root 115: static struct obstack obstack, obstack1, obstack2; 1.1 root 116: struct obstack *rtl_obstack = &obstack; 1.1.1.3 root 117: struct obstack *hash_obstack = &obstack1; 118: struct obstack *temp_obstack = &obstack2; 1.1 root 119: 120: #define obstack_chunk_alloc xmalloc 121: #define obstack_chunk_free free 122: 1.1.1.3 root 123: /* Define this so we can link with print-rtl.o to get debug_rtx function. */ 124: char **insn_name_ptr = 0; 125: 1.1 root 126: extern void free (); 1.1.1.3 root 127: extern rtx read_rtx (); 1.1 root 128: 129: static void fatal (); 130: void fancy_abort (); 131: 1.1.1.4 root 132: /* enough space to reserve for printing out ints */ 133: #define MAX_DIGITS (HOST_BITS_PER_INT * 3 / 10 + 3) 134: 1.1 root 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. */ 1.1.1.4 root 183: int negative_ok; /* Allow negative numeric values. */ 184: int unsigned_p; /* Make the output function unsigned int. */ 1.1.1.2 root 185: int is_const; /* Attribute value constant for each run. */ 1.1 root 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: 1.1.1.4 root 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: 1.1 root 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. */ 1.1.1.4 root 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. */ 1.1 root 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. */ 1.1.1.4 root 238: int needs_blockage_function; /* Nonzero if a blockage function required. */ 1.1.1.5 root 239: int needs_range_function; /* Nonzero if blockage range function needed.*/ 1.1 root 240: rtx default_cost; /* Conflict cost, if constant. */ 1.1.1.4 root 241: struct range issue_delay; /* Range of issue delay values. */ 242: int max_blockage; /* Maximum time an insn blocks the unit. */ 1.1 root 243: }; 244: 245: /* Listheads of above structures. */ 246: 1.1.1.3 root 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]; 1.1 root 250: static struct insn_def *defs; 251: static struct delay_desc *delays; 252: static struct function_unit *units; 253: 1.1.1.5 root 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: 1.1 root 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; 1.1.1.4 root 305: static int length_used; 1.1 root 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: 1.1.1.4 root 312: enum operator {PLUS_OP, MINUS_OP, POS_MINUS_OP, EQ_OP, OR_OP, MAX_OP, MIN_OP, RANGE_OP}; 1.1 root 313: 1.1.1.3 root 314: /* Stores, for each insn code, the number of constraint alternatives. */ 315: 316: static int *insn_n_alternatives; 317: 1.1 root 318: /* Stores, for each insn code, a bitmap that has bits on for each possible 319: alternative. */ 320: 321: static int *insn_alternatives; 322: 1.1.1.3 root 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: 1.1 root 329: /* Used to simplify expressions. */ 330: 331: static rtx true_rtx, false_rtx; 332: 333: /* Used to reduce calls to `strcmp' */ 334: 1.1.1.3 root 335: static char *alternative_name; 1.1 root 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) \ 1.1.1.3 root 340: (RTX_UNCHANGING_P (EXP) || MEM_IN_STRUCT_P (EXP) ? (EXP) \ 1.1 root 341: : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX)) 342: 1.1.1.3 root 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: 1.1 root 352: /* These are referenced by rtlanal.c and hence need to be defined somewhere. 353: They won't actually be used. */ 354: 1.1.1.6 ! root 355: rtx frame_pointer_rtx, hard_frame_pointer_rtx, stack_pointer_rtx; ! 356: rtx arg_pointer_rtx; 1.1 root 357: 1.1.1.5 root 358: #if 0 359: static rtx attr_rtx PROTO((enum rtx_code, ...)); 360: static char *attr_printf PROTO((int, char *, ...)); 361: #else 1.1.1.2 root 362: static rtx attr_rtx (); 363: static char *attr_printf (); 1.1.1.5 root 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 *)); 1.1.1.6 ! root 383: /* dpx2 compiler chokes if we specify the arg types of the args. */ ! 384: static rtx substitute_address PROTO((rtx, rtx (*) (), rtx (*) ())); 1.1.1.5 root 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)); 1.1.1.4 root 446: 447: #define oballoc(size) obstack_alloc (hash_obstack, size) 448: 1.1 root 449: 1.1.1.2 root 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. */ 1.1.1.4 root 479: #define RTL_HASH(RTL) ((HOST_WIDE_INT) (RTL) & 0777777) 1.1.1.2 root 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: 1.1.1.3 root 490: h = (struct attr_hash *) obstack_alloc (hash_obstack, 491: sizeof (struct attr_hash)); 1.1.1.2 root 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: 1.1.1.3 root 507: h = (struct attr_hash *) obstack_alloc (hash_obstack, 508: sizeof (struct attr_hash)); 1.1.1.2 root 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: 1.1.1.3 root 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: 1.1.1.2 root 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; 1.1.1.3 root 537: struct obstack *old_obstack = rtl_obstack; 1.1.1.2 root 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: 1.1.1.3 root 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: 1.1.1.4 root 559: hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0)); 1.1.1.2 root 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: { 1.1.1.3 root 568: rtl_obstack = hash_obstack; 1.1.1.2 root 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: 1.1.1.3 root 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: 1.1.1.4 root 590: hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1)); 1.1.1.2 root 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: { 1.1.1.3 root 600: rtl_obstack = hash_obstack; 1.1.1.2 root 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: 1.1.1.3 root 611: if (code == SYMBOL_REF) 612: arg0 = attr_string (arg0, strlen (arg0)); 613: 1.1.1.4 root 614: hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0)); 1.1.1.2 root 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: { 1.1.1.3 root 623: rtl_obstack = hash_obstack; 1.1.1.2 root 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: { 1.1.1.3 root 632: char *arg0 = va_arg (p, char *); 633: char *arg1 = va_arg (p, char *); 1.1.1.2 root 634: 1.1.1.4 root 635: hashcode = ((HOST_WIDE_INT) code + RTL_HASH (arg0) + RTL_HASH (arg1)); 1.1.1.2 root 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: { 1.1.1.3 root 645: rtl_obstack = hash_obstack; 1.1.1.2 root 646: rt_val = rtx_alloc (code); 647: XSTR (rt_val, 0) = arg0; 648: XSTR (rt_val, 1) = arg1; 649: } 650: } 1.1.1.3 root 651: else if (code == CONST_INT) 652: { 1.1.1.4 root 653: HOST_WIDE_INT arg0 = va_arg (p, HOST_WIDE_INT); 1.1.1.3 root 654: if (arg0 == 0) 655: return false_rtx; 656: if (arg0 == 1) 657: return true_rtx; 658: goto nohash; 659: } 1.1.1.2 root 660: else 661: { 1.1.1.3 root 662: nohash: 1.1.1.2 root 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: 1.1.1.4 root 677: case 'w': /* A wide integer? */ 678: XWINT (rt_val, i) = va_arg (p, HOST_WIDE_INT); 679: break; 680: 1.1.1.2 root 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: 1.1.1.3 root 702: rtl_obstack = old_obstack; 1.1.1.2 root 703: va_end (p); 704: attr_hash_add_rtx (hashcode, rt_val); 1.1.1.3 root 705: RTX_INTEGRATED_P (rt_val) = 1; 1.1.1.2 root 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: 1.1.1.3 root 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: 1.1.1.2 root 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) 1.1.1.3 root 796: if (h->hashcode == -hashcode && h->u.str[0] == str[0] 1.1.1.2 root 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. */ 1.1.1.3 root 801: new_str = (char *) obstack_alloc (hash_obstack, len + 1); 1.1.1.2 root 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: } 1.1.1.3 root 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: 1.1.1.4 root 883: case 'n': 884: case 'i': 1.1.1.3 root 885: XINT (copy, i) = XINT (orig, i); 886: break; 1.1.1.4 root 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 (); 1.1.1.3 root 899: } 900: } 901: return copy; 902: } 1.1.1.2 root 903: 1.1 root 904: /* Given a test expression for an attribute, ensure it is validly formed. 1.1.1.2 root 905: IS_CONST indicates whether the expression is constant for each compiler 906: run (a constant expression may not test any particular insn). 907: 1.1 root 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 1.1.1.2 root 919: check_attr_test (exp, is_const) 1.1 root 920: rtx exp; 1.1.1.2 root 921: int is_const; 1.1 root 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] == '!') 1.1.1.2 root 933: return check_attr_test (attr_rtx (NOT, 1.1.1.3 root 934: attr_eq (XSTR (exp, 0), 935: &XSTR (exp, 1)[1])), 1.1.1.2 root 936: is_const); 1.1 root 937: 938: else if (n_comma_elts (XSTR (exp, 1)) == 1) 939: { 1.1.1.3 root 940: attr = find_attr (XSTR (exp, 0), 0); 1.1 root 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: } 1.1.1.3 root 950: else 1.1 root 951: fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0)); 952: } 953: 1.1.1.2 root 954: if (is_const && ! attr->is_const) 955: fatal ("Constant expression uses insn attribute `%s' in EQ_ATTR", 956: XEXP (exp, 0)); 957: 1.1.1.3 root 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: 1.1.1.4 root 962: /* It shouldn't be possible to simplify the value given to a 1.1.1.3 root 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; 1.1 root 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: { 1.1.1.3 root 994: newexp = attr_eq (XSTR (exp, 0), p); 1.1.1.5 root 995: orexp = insert_right_side (IOR, orexp, newexp, -2, -2); 1.1 root 996: } 997: 1.1.1.2 root 998: return check_attr_test (orexp, is_const); 1.1 root 999: } 1000: break; 1001: 1.1.1.5 root 1002: case ATTR_FLAG: 1003: break; 1004: 1.1 root 1005: case CONST_INT: 1006: /* Either TRUE or FALSE. */ 1.1.1.4 root 1007: if (XWINT (exp, 0)) 1.1 root 1008: return true_rtx; 1009: else 1010: return false_rtx; 1011: 1012: case IOR: 1013: case AND: 1.1.1.2 root 1014: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const); 1015: XEXP (exp, 1) = check_attr_test (XEXP (exp, 1), is_const); 1.1 root 1016: break; 1017: 1018: case NOT: 1.1.1.2 root 1019: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), is_const); 1.1 root 1020: break; 1021: 1022: case MATCH_OPERAND: 1.1.1.2 root 1023: if (is_const) 1024: fatal ("RTL operator \"%s\" not valid in constant attribute test", 1025: GET_RTX_NAME (MATCH_OPERAND)); 1.1.1.3 root 1026: /* These cases can't be simplified. */ 1027: RTX_UNCHANGING_P (exp) = 1; 1028: break; 1.1.1.2 root 1029: 1.1 root 1030: case LE: case LT: case GT: case GE: 1031: case LEU: case LTU: case GTU: case GEU: 1032: case NE: case EQ: 1.1.1.3 root 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))); 1.1 root 1038: /* These cases can't be simplified. */ 1039: RTX_UNCHANGING_P (exp) = 1; 1040: break; 1041: 1.1.1.2 root 1042: case SYMBOL_REF: 1043: if (is_const) 1044: { 1045: /* These cases are valid for constant attributes, but can't be 1046: simplified. */ 1.1.1.3 root 1047: exp = attr_rtx (SYMBOL_REF, XSTR (exp, 0)); 1.1.1.2 root 1048: RTX_UNCHANGING_P (exp) = 1; 1049: break; 1050: } 1.1 root 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 1.1.1.3 root 1061: if not. If no attribute is specified, assume a numeric attribute. 1.1 root 1062: 1.1.1.3 root 1063: Return a perhaps modified replacement expression for the value. */ 1064: 1065: static rtx 1.1 root 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: { 1.1.1.4 root 1093: p = XSTR (exp, 0); 1094: if (attr && attr->negative_ok && *p == '-') 1095: p++; 1096: for (; *p; p++) 1.1 root 1097: if (*p > '9' || *p < '0') 1098: fatal ("Non-numeric value for numeric `%s' attribute", 1.1.1.3 root 1099: attr ? attr->name : "internal"); 1.1 root 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", 1.1.1.3 root 1110: XSTR (exp, 0), attr ? attr->name : "internal"); 1.1 root 1111: 1.1.1.3 root 1112: break; 1.1 root 1113: 1114: case IF_THEN_ELSE: 1.1.1.2 root 1115: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0), 1116: attr ? attr->is_const : 0); 1.1.1.3 root 1117: XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr); 1118: XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr); 1119: break; 1.1 root 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: { 1.1.1.2 root 1127: XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i), 1128: attr ? attr->is_const : 0); 1.1.1.3 root 1129: XVECEXP (exp, 0, i + 1) 1130: = check_attr_value (XVECEXP (exp, 0, i + 1), attr); 1.1 root 1131: } 1132: 1.1.1.3 root 1133: XEXP (exp, 1) = check_attr_value (XEXP (exp, 1), attr); 1134: break; 1.1 root 1135: 1.1.1.2 root 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. */ 1.1.1.3 root 1140: return attr_rtx (SYMBOL_REF, XSTR (exp, 0)); 1.1.1.2 root 1141: /* Otherwise, fall through... */ 1142: 1.1 root 1143: default: 1144: fatal ("Illegal operation `%s' for attribute value", 1145: GET_RTX_NAME (GET_CODE (exp))); 1146: } 1.1.1.3 root 1147: 1148: return exp; 1.1 root 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: { 1.1.1.2 root 1174: char *p; 1.1.1.3 root 1175: p = attr_numeral (i); 1.1.1.2 root 1176: 1.1.1.3 root 1177: XVECEXP (condexp, 0, 2 * i) = attr_eq (alternative_name, p); 1178: #if 0 1.1.1.2 root 1179: /* Sharing this EQ_ATTR rtl causes trouble. */ 1.1 root 1180: XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR); 1181: XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name; 1.1.1.2 root 1182: XSTR (XVECEXP (condexp, 0, 2 * i), 1) = p; 1.1.1.3 root 1183: #endif 1.1 root 1184: XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i); 1185: } 1186: 1187: XEXP (condexp, 1) = XVECEXP (exp, 1, i); 1188: 1.1.1.2 root 1189: return attr_rtx (SET, attr_rtx (ATTR, XSTR (exp, 0)), condexp); 1.1 root 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) 1.1.1.2 root 1209: return attr_rtx (SET, 1210: attr_rtx (ATTR, XSTR (exp, 0)), 1211: attr_rtx (CONST_STRING, XSTR (exp, 1))); 1.1 root 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) 1.1.1.2 root 1221: XVECEXP (newexp, 1, n++) = attr_rtx (CONST_STRING, p); 1.1 root 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; 1.1.1.3 root 1275: XEXP (value, 1) = check_attr_value (XEXP (value, 1), attr); 1.1 root 1276: } 1277: } 1278: } 1279: 1.1.1.2 root 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: { 1.1.1.3 root 1307: char *p, *string; 1.1.1.2 root 1308: rtx value; 1309: 1.1.1.4 root 1310: string = p = (char *) oballoc (2 1.1.1.3 root 1311: + strlen (attr->name) 1312: + strlen (XSTR (av->value, 0))); 1.1.1.2 root 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: 1.1.1.3 root 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: 1.1.1.2 root 1325: XVECEXP (condexp, 0, 2 * i + 1) = av->value; 1326: } 1327: 1328: return condexp; 1329: } 1330: 1.1 root 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: 1.1.1.2 root 1360: case SYMBOL_REF: 1361: if (!attr->is_const || RTX_UNCHANGING_P (exp)) 1362: break; 1.1.1.3 root 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. */ 1.1.1.2 root 1366: RTX_UNCHANGING_P (exp) = 1; 1367: exp = convert_const_symbol_ref (exp, attr); 1.1.1.3 root 1368: RTX_UNCHANGING_P (exp) = 1; 1369: exp = check_attr_value (exp, attr); 1.1.1.2 root 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: 1.1 root 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: 1.1.1.2 root 1387: cond: 1.1.1.3 root 1388: { 1389: int allsame = 1; 1390: rtx defval; 1.1 root 1391: 1.1.1.3 root 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)); 1.1 root 1396: 1.1.1.3 root 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: } 1.1 root 1409: } 1410: 1411: return exp; 1412: } 1.1.1.3 root 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: } 1.1 root 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: 1.1.1.4 root 1457: av = (struct attr_value *) oballoc (sizeof (struct attr_value)); 1.1 root 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: 1.1.1.3 root 1479: Normal attribute filling and optimization expands these to contain the 1.1 root 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: 1.1.1.3 root 1522: /* For each delay possibility and delay slot, compute an eligibility 1523: attribute for non-annulled insns and for each type of annulled (annul 1.1 root 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; 1.1.1.2 root 1531: newexp = attr_rtx (IF_THEN_ELSE, condexp, 1532: make_numeric_value (1), make_numeric_value (0)); 1.1 root 1533: 1.1.1.4 root 1534: p = attr_printf (sizeof ("*delay__") + MAX_DIGITS*2, "*delay_%d_%d", 1535: delay->num, i / 3); 1.1 root 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; 1.1.1.2 root 1542: newexp = attr_rtx (IF_THEN_ELSE, condexp, 1543: make_numeric_value (1), 1544: make_numeric_value (0)); 1.1.1.4 root 1545: p = attr_printf (sizeof ("*annul_true__") + MAX_DIGITS*2, 1546: "*annul_true_%d_%d", delay->num, i / 3); 1.1 root 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; 1.1.1.2 root 1554: newexp = attr_rtx (IF_THEN_ELSE, condexp, 1555: make_numeric_value (1), 1556: make_numeric_value (0)); 1.1.1.4 root 1557: p = attr_printf (sizeof ("*annul_false__") + MAX_DIGITS*2, 1558: "*annul_false_%d_%d", delay->num, i / 3); 1.1 root 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: 1.1.1.4 root 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: 1.1 root 1607: case OR_OP: 1608: i = left_value | right_value; 1609: break; 1610: 1.1.1.4 root 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: 1.1 root 1619: case MAX_OP: 1620: if (left_value > right_value) 1621: i = left_value; 1622: else 1623: i = right_value; 1624: break; 1625: 1.1.1.4 root 1626: case MIN_OP: 1627: if (left_value < right_value) 1628: i = left_value; 1629: else 1630: i = right_value; 1631: break; 1632: 1.1 root 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. */ 1.1.1.3 root 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); 1.1 root 1647: } 1648: else if (GET_CODE (right) == COND) 1649: { 1.1.1.3 root 1650: int allsame = 1; 1651: rtx defval; 1652: 1.1 root 1653: newexp = rtx_alloc (COND); 1654: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0)); 1.1.1.3 root 1655: defval = XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1)); 1656: 1.1 root 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)); 1.1.1.3 root 1662: if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1), 1663: defval)) 1664: allsame = 0; 1.1 root 1665: } 1666: 1.1.1.3 root 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: } 1.1 root 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: { 1.1.1.3 root 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); 1.1 root 1697: } 1698: else if (GET_CODE (left) == COND) 1699: { 1.1.1.3 root 1700: int allsame = 1; 1701: rtx defval; 1702: 1.1 root 1703: newexp = rtx_alloc (COND); 1704: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0)); 1.1.1.3 root 1705: defval = XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right); 1706: 1.1 root 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); 1.1.1.3 root 1712: if (! rtx_equal_p (XVECEXP (newexp, 0, i + 1), 1713: defval)) 1714: allsame = 0; 1.1 root 1715: } 1716: 1.1.1.3 root 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: } 1.1 root 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 1.1.1.4 root 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. 1.1 root 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 1.1.1.4 root 1761: and a `<name>_unit_conflict_cost' function is given an insn already 1.1 root 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 1.1.1.4 root 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. */ 1.1 root 1773: 1774: static void 1775: expand_units () 1776: { 1.1.1.4 root 1777: struct function_unit *unit, **unit_num; 1778: struct function_unit_op *op, **op_array, ***unit_ops; 1.1 root 1779: rtx unitsmask; 1780: rtx readycost; 1781: rtx newexp; 1782: char *str; 1.1.1.4 root 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); 1.1 root 1794: 1.1.1.4 root 1795: unit->condexp = check_attr_test (unit->condexp, 0); 1.1 root 1796: 1.1.1.4 root 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); 1.1 root 1830: newexp = rtx_alloc (IF_THEN_ELSE); 1831: XEXP (newexp, 2) = make_numeric_value (0); 1832: 1.1.1.4 root 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: 1.1 root 1859: for (unit = units; unit; unit = unit->next) 1860: { 1.1.1.4 root 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) 1.1.1.5 root 1927: orexp = insert_right_side (IOR, orexp, op->condexp, -2, -2); 1.1.1.4 root 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; 1.1 root 2076: 1.1.1.4 root 2077: caseexp = rtx_alloc (COND); 1.1 root 2078: XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); 2079: 2080: for (op = unit->ops; op; op = op->next) 2081: { 1.1.1.4 root 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. */ 1.1 root 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: 1.1.1.4 root 2097: /* Simplifying caseexp with simplify_by_exploding doesn't win. */ 2098: str = attr_printf (strlen (unit->name) + sizeof ("*_cases"), 2099: "*%s_cases", unit->name); 1.1 root 2100: make_internal_attr (str, caseexp, 1); 1.1.1.4 root 2101: } 2102: } 1.1 root 2103: 1.1.1.4 root 2104: /* Simplify EXP given KNOWN_TRUE. */ 1.1 root 2105: 1.1.1.4 root 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); 1.1 root 2115: } 1.1.1.4 root 2116: return exp; 2117: } 1.1 root 2118: 1.1.1.4 root 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; 1.1 root 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: 1.1.1.3 root 2197: /* Don't fill constant attributes. The value is independent of 2198: any particular insn. */ 2199: if (attr->is_const) 2200: return; 2201: 1.1 root 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: 1.1.1.4 root 2218: ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent)); 1.1 root 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: 1.1.1.2 root 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)); 1.1 root 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"}; 1.1.1.5 root 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}; 1.1 root 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: 1.1.1.2 root 2328: length_attr->is_const = 0; 1.1 root 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); 1.1.1.4 root 2346: new_ie = (struct insn_ent *) oballoc (sizeof (struct insn_ent)); 1.1 root 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: 1.1.1.3 root 2390: We do not modify EXP; rather, we make and return a new rtx. */ 1.1 root 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; 1.1.1.3 root 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; 1.1.1.4 root 2406: char *first_spacer; 1.1.1.3 root 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); 1.1 root 2416: 1.1.1.3 root 2417: /* Simplify the subexpressions, and see what tests we can get rid of. */ 2418: 2419: for (i = 0; i < len; i += 2) 1.1 root 2420: { 1.1.1.3 root 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. */ 1.1 root 2433: if (newtest == true_rtx) 2434: { 1.1.1.3 root 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; 1.1 root 2440: } 2441: 2442: else if (newtest == false_rtx) 2443: { 1.1.1.3 root 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; 1.1 root 2448: } 2449: 1.1.1.3 root 2450: else if (i > 0 && attr_equal_p (newval, tests[i - 1])) 1.1 root 2451: { 1.1.1.3 root 2452: /* If this value and the value for the prev test are the same, 2453: merge the tests. */ 1.1 root 2454: 1.1.1.3 root 2455: tests[i - 2] 2456: = insert_right_side (IOR, tests[i - 2], newtest, 1.1 root 2457: insn_code, insn_index); 2458: 1.1.1.3 root 2459: /* Delete this test/value. */ 2460: for (j = i; j < len - 2; j++) 2461: tests[j] = tests[j + 2]; 2462: len -= 2; 1.1 root 2463: } 2464: 1.1.1.3 root 2465: else 2466: tests[i + 1] = newval; 2467: } 1.1 root 2468: 1.1.1.3 root 2469: /* If the last test in a COND has the same value 2470: as the default value, that test isn't needed. */ 1.1 root 2471: 1.1.1.3 root 2472: while (len > 0 && attr_equal_p (tests[len - 1], new_defval)) 2473: len -= 2; 1.1 root 2474: 1.1.1.3 root 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; 1.1 root 2483: break; 2484: } 2485: 1.1.1.3 root 2486: if (len == 0) 1.1 root 2487: { 1.1.1.3 root 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; 1.1 root 2497: } 2498: else 1.1.1.3 root 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: } 1.1 root 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) 1.1.1.5 root 2557: enum rtx_code code; 1.1 root 2558: rtx exp; 2559: rtx term; 2560: int insn_code, insn_index; 2561: { 2562: rtx newexp; 2563: 1.1.1.3 root 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: 1.1 root 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: { 1.1.1.3 root 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; 1.1 root 2603: } 2604: else 2605: { 2606: /* Insert the new term. */ 1.1.1.2 root 2607: newexp = attr_rtx (code, exp, term); 1.1.1.3 root 2608: } 1.1 root 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 1.1.1.5 root 2619: bitmask indicating which alternatives are mentioned within EXP. */ 1.1 root 2620: 2621: static int 2622: compute_alternative_mask (exp, code) 2623: rtx exp; 1.1.1.5 root 2624: enum rtx_code code; 1.1 root 2625: { 1.1.1.3 root 2626: char *string; 1.1 root 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) 1.1.1.3 root 2634: string = XSTR (XEXP (exp, 0), 1); 1.1 root 2635: 2636: else if (code == IOR && GET_CODE (exp) == EQ_ATTR 2637: && XSTR (exp, 0) == alternative_name) 1.1.1.3 root 2638: string = XSTR (exp, 1); 1.1 root 2639: 2640: else 2641: return 0; 1.1.1.3 root 2642: 2643: if (string[1] == 0) 2644: return 1 << (string[0] - '0'); 2645: return 1 << atoi (string); 1.1 root 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: 1.1.1.3 root 2662: newexp = attr_rtx (EQ_ATTR, alternative_name, attr_numeral (i)); 1.1 root 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 1.1.1.5 root 2672: intact because addresses are only valid for the `length' attribute. 1.1 root 2673: 1.1.1.5 root 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. */ 1.1.1.3 root 2676: 1.1 root 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: 1.1.1.3 root 2712: if (current_alternative_string) 2713: clear_struct_flag (value); 2714: 1.1 root 2715: for (i = 0; i < XVECLEN (value, 0); i += 2) 2716: { 1.1.1.3 root 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, 1.1 root 2723: insn_code, insn_index); 2724: right = insert_right_side (AND, right, 1.1.1.5 root 2725: evaluate_eq_attr (exp, 2726: XVECEXP (value, 0, 2727: i + 1), 2728: insn_code, insn_index), 1.1 root 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. */ 1.1.1.3 root 2734: newexp = attr_rtx (NOT, this); 1.1 root 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), 1.1.1.5 root 2742: insn_code, insn_index), 1.1 root 2743: insn_code, insn_index); 2744: newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index); 2745: } 2746: else 2747: abort (); 2748: 1.1.1.3 root 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. */ 1.1 root 2751: 2752: address_used = 0; 2753: walk_attr_value (newexp); 2754: 2755: if (address_used) 1.1.1.3 root 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: } 1.1 root 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: { 1.1.1.2 root 2797: newexp = attr_rtx (GET_CODE (exp), left, right); 1.1 root 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: { 1.1.1.2 root 2820: newexp = attr_rtx (GET_CODE (exp), left, right); 1.1 root 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: { 1.1.1.3 root 2875: if (attr_equal_p (XEXP (exp, 0), XEXP (*pterm, 0))) 1.1 root 2876: return true_rtx; 2877: } 2878: 2879: else if (GET_CODE (exp) == NOT) 2880: { 1.1.1.3 root 2881: if (attr_equal_p (XEXP (exp, 0), *pterm)) 1.1 root 2882: return false_rtx; 2883: } 2884: 2885: else if (GET_CODE (*pterm) == NOT) 2886: { 1.1.1.3 root 2887: if (attr_equal_p (XEXP (*pterm, 0), exp)) 1.1 root 2888: return false_rtx; 2889: } 2890: 1.1.1.3 root 2891: else if (attr_equal_p (exp, *pterm)) 1.1 root 2892: return true_rtx; 2893: 2894: return exp; 2895: } 2896: 1.1.1.3 root 2897: /* Similar to `simplify_and_tree', but for IOR trees. */ 1.1 root 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: { 1.1.1.2 root 2916: newexp = attr_rtx (GET_CODE (exp), left, right); 1.1 root 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: { 1.1.1.2 root 2939: newexp = attr_rtx (GET_CODE (exp), left, right); 1.1 root 2940: 2941: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); 2942: } 2943: } 2944: 1.1.1.3 root 2945: if (attr_equal_p (exp, *pterm)) 1.1 root 2946: return false_rtx; 2947: 1.1.1.3 root 2948: else if (GET_CODE (exp) == NOT && attr_equal_p (XEXP (exp, 0), *pterm)) 1.1 root 2949: return true_rtx; 2950: 1.1.1.3 root 2951: else if (GET_CODE (*pterm) == NOT && attr_equal_p (XEXP (*pterm, 0), exp)) 1.1 root 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; 1.1.1.3 root 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; 1.1 root 2992: 2993: switch (GET_CODE (exp)) 2994: { 2995: case AND: 2996: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index); 1.1.1.3 root 2997: SIMPLIFY_ALTERNATIVE (left); 2998: if (left == false_rtx) 2999: { 3000: obstack_free (rtl_obstack, spacer); 3001: return false_rtx; 3002: } 1.1 root 3003: right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index); 1.1.1.3 root 3004: SIMPLIFY_ALTERNATIVE (right); 3005: if (left == false_rtx) 3006: { 3007: obstack_free (rtl_obstack, spacer); 3008: return false_rtx; 3009: } 1.1 root 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 1.1.1.2 root 3013: yield simplifications. */ 1.1 root 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: 1.1.1.2 root 3025: newexp = attr_rtx (IOR, 3026: attr_rtx (AND, left, XEXP (right, 0)), 3027: attr_rtx (AND, left, XEXP (right, 1))); 1.1 root 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) 1.1.1.3 root 3038: { 3039: obstack_free (rtl_obstack, spacer); 3040: return false_rtx; 3041: } 1.1 root 3042: else if (left == true_rtx) 1.1.1.3 root 3043: { 3044: return right; 3045: } 1.1 root 3046: else if (right == true_rtx) 1.1.1.3 root 3047: { 3048: return left; 3049: } 1.1 root 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); 1.1.1.2 root 3080: newexp = attr_rtx (AND, left, right); 1.1 root 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: { 1.1.1.2 root 3088: newexp = attr_rtx (AND, left, right); 1.1 root 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); 1.1.1.3 root 3095: SIMPLIFY_ALTERNATIVE (left); 3096: if (left == true_rtx) 3097: { 3098: obstack_free (rtl_obstack, spacer); 3099: return true_rtx; 3100: } 1.1 root 3101: right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index); 1.1.1.3 root 3102: SIMPLIFY_ALTERNATIVE (right); 3103: if (right == true_rtx) 3104: { 3105: obstack_free (rtl_obstack, spacer); 3106: return true_rtx; 3107: } 1.1 root 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) 1.1.1.3 root 3114: { 3115: obstack_free (rtl_obstack, spacer); 3116: return true_rtx; 3117: } 1.1 root 3118: else if (left == false_rtx) 1.1.1.3 root 3119: { 3120: return right; 3121: } 1.1 root 3122: else if (right == false_rtx) 1.1.1.3 root 3123: { 3124: return left; 3125: } 1.1 root 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 1.1.1.3 root 3135: && attr_equal_p (XEXP (left, 0), XEXP (right, 0))) 1.1 root 3136: { 1.1.1.2 root 3137: newexp = attr_rtx (IOR, XEXP (left, 1), XEXP (right, 1)); 1.1 root 3138: 3139: left = XEXP (left, 0); 3140: right = newexp; 1.1.1.2 root 3141: newexp = attr_rtx (AND, left, right); 1.1 root 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); 1.1.1.2 root 3173: newexp = attr_rtx (IOR, attr_rtx (NOT, left), right); 1.1 root 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: { 1.1.1.2 root 3181: newexp = attr_rtx (IOR, left, right); 1.1 root 3182: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); 3183: } 3184: break; 3185: 3186: case NOT: 1.1.1.3 root 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: 1.1 root 3195: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index); 1.1.1.3 root 3196: SIMPLIFY_ALTERNATIVE (left); 1.1 root 3197: if (GET_CODE (left) == NOT) 3198: return XEXP (left, 0); 3199: 3200: if (left == false_rtx) 1.1.1.3 root 3201: { 3202: obstack_free (rtl_obstack, spacer); 3203: return true_rtx; 3204: } 1.1 root 3205: else if (left == true_rtx) 1.1.1.3 root 3206: { 3207: obstack_free (rtl_obstack, spacer); 3208: return false_rtx; 3209: } 1.1 root 3210: 3211: /* Try to apply De`Morgan's laws. */ 3212: else if (GET_CODE (left) == IOR) 3213: { 1.1.1.2 root 3214: newexp = attr_rtx (AND, 3215: attr_rtx (NOT, XEXP (left, 0)), 3216: attr_rtx (NOT, XEXP (left, 1))); 1.1 root 3217: 3218: newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); 3219: } 3220: else if (GET_CODE (left) == AND) 3221: { 1.1.1.2 root 3222: newexp = attr_rtx (IOR, 3223: attr_rtx (NOT, XEXP (left, 0)), 3224: attr_rtx (NOT, XEXP (left, 1))); 1.1 root 3225: 3226: newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); 3227: } 3228: else if (left != XEXP (exp, 0)) 3229: { 1.1.1.2 root 3230: newexp = attr_rtx (NOT, left); 1.1 root 3231: } 3232: break; 3233: 3234: case EQ_ATTR: 1.1.1.3 root 3235: if (current_alternative_string && XSTR (exp, 0) == alternative_name) 3236: return (XSTR (exp, 1) == current_alternative_string 3237: ? true_rtx : false_rtx); 3238: 1.1 root 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.). */ 1.1.1.3 root 3253: if (insn_code != -2 /* Seems wrong: && current_alternative_string. */ 3254: && ! RTX_UNCHANGING_P (newexp)) 3255: return copy_rtx_unchanging (newexp); 1.1 root 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; 1.1.1.4 root 3269: struct insn_ent *ie; 1.1 root 3270: rtx newexp; 3271: int something_changed = 1; 1.1.1.3 root 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; 1.1 root 3291: 1.1.1.3 root 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++) 1.1 root 3308: { 1.1.1.3 root 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); 1.1 root 3323: 1.1.1.3 root 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 1.1 root 3338: newexp = simplify_cond (av->value, ie->insn_code, 3339: ie->insn_index); 1.1.1.3 root 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: } 1.1 root 3354: } 3355: } 1.1.1.3 root 3356: 1.1.1.4 root 3357: #if 0 1.1.1.3 root 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: } 1.1.1.4 root 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: { 1.1.1.5 root 3664: orexp = insert_right_side (IOR, orexp, XEXP (link, 0), -2, -2); 1.1.1.4 root 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++) 1.1.1.5 root 3708: exp = insert_right_side (AND, exp, XEXP (space[i].current_value, 0), 3709: -2, -2); 1.1.1.4 root 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: } 1.1.1.3 root 3825: 3826: /* Clear the MEM_IN_STRUCT_P flag in EXP and its subexpressions. */ 3827: 1.1.1.5 root 3828: static void 1.1.1.3 root 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: 1.1.1.5 root 3854: case ATTR_FLAG: 1.1.1.3 root 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: 1.1.1.5 root 3882: static int 1.1.1.3 root 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: 1.1.1.5 root 3906: case ATTR_FLAG: 1.1.1.3 root 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: } 1.1 root 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: { 1.1.1.4 root 3960: av = (struct attr_value *) oballoc (sizeof (struct attr_value)); 1.1.1.2 root 3961: av->value = attr_rtx (CONST_STRING, p); 1.1 root 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: 1.1.1.2 root 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: 1.1 root 3979: if (! strcmp (attr->name, "length") && ! attr->is_numeric) 3980: fatal ("`length' attribute must take numeric values"); 3981: 3982: /* Set up the default value. */ 1.1.1.3 root 3983: XEXP (exp, 2) = check_attr_value (XEXP (exp, 2), attr); 1.1 root 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: 1.1.1.4 root 4100: id = (struct insn_def *) oballoc (sizeof (struct insn_def)); 1.1 root 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: 1.1.1.4 root 4156: delay = (struct delay_desc *) oballoc (sizeof (struct delay_desc)); 1.1 root 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; 1.1.1.4 root 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); 1.1 root 4181: 4182: /* See if we have already seen this function unit. If so, check that 1.1.1.3 root 4183: the multiplicity and simultaneity values are the same. If not, make 1.1 root 4184: a structure for this function unit. */ 4185: for (unit = units; unit; unit = unit->next) 1.1.1.4 root 4186: if (! strcmp (unit->name, name)) 1.1 root 4187: { 1.1.1.4 root 4188: if (unit->multiplicity != multiplicity 4189: || unit->simultaneity != simultaneity) 1.1 root 4190: fatal ("Differing specifications given for `%s' function unit.", 4191: unit->name); 4192: break; 4193: } 4194: 4195: if (unit == 0) 4196: { 1.1.1.4 root 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; 1.1 root 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. */ 1.1.1.4 root 4211: op = (struct function_unit_op *) oballoc (sizeof (struct function_unit_op)); 4212: op->condexp = condexp; 1.1 root 4213: op->num = unit->num_opclasses++; 1.1.1.4 root 4214: op->ready = ready_cost; 4215: op->issue_delay = issue_delay; 1.1 root 4216: op->next = unit->ops; 4217: unit->ops = op; 4218: 1.1.1.4 root 4219: /* Set our issue expression based on whether or not an optional conflict 1.1 root 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++) 1.1.1.5 root 4228: orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2, -2); 1.1 root 4229: 1.1.1.4 root 4230: op->conflict_exp = orexp; 4231: extend_range (&unit->issue_delay, 1, issue_delay); 1.1 root 4232: } 4233: else 1.1.1.4 root 4234: { 4235: op->conflict_exp = true_rtx; 4236: extend_range (&unit->issue_delay, issue_delay, issue_delay); 4237: } 1.1 root 4238: 4239: /* Merge our conditional into that of the function unit so we can determine 4240: which insns are used by the function unit. */ 1.1.1.5 root 4241: unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2, -2); 1.1 root 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: 1.1.1.2 root 4320: printf (" %% "); 1.1 root 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 (); 1.1.1.3 root 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, 1.1.1.5 root 4402: -2, -2), 1.1.1.3 root 4403: in_comparison); 4404: } 4405: else 4406: { 4407: printf ("get_attr_%s (insn) == ", attr->name); 4408: write_attr_valueq (attr, XSTR (exp, 1)); 4409: } 1.1 root 4410: break; 4411: 1.1.1.5 root 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: 1.1 root 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: 1.1.1.4 root 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 1.1 root 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: 1.1.1.4 root 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: 1.1 root 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 1.1.1.4 root 4520: `length_used' if an (eq_attr "length" ...) was used 1.1 root 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: 1.1.1.2 root 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; 1.1 root 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; 1.1.1.4 root 4552: else if (strcmp (XSTR (exp, 0), "length") == 0) 4553: length_used = 1; 1.1 root 4554: return; 4555: 4556: case MATCH_DUP: 4557: case PC: 4558: address_used = 1; 4559: return; 1.1.1.5 root 4560: 4561: case ATTR_FLAG: 4562: return; 1.1 root 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. */ 1.1.1.4 root 4595: if (!attr->is_numeric) 1.1 root 4596: printf ("enum attr_%s\n", attr->name); 1.1.1.4 root 4597: else if (attr->unsigned_p) 4598: printf ("unsigned int\n"); 4599: else 4600: printf ("int\n"); 1.1 root 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]); 1.1.1.2 root 4606: else if (attr->is_const == 0) 1.1 root 4607: printf ("get_attr_%s (insn)\n", attr->name); 1.1.1.2 root 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: } 1.1 root 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); 1.1.1.2 root 4707: newexp = attr_rtx (NOT, testexp); 1.1 root 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 1.1.1.5 root 4769: write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, 4770: known_true) 1.1 root 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: 1.1.1.4 root 4810: /* See what we have to do to output this value. */ 1.1 root 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) 1.1.1.4 root 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: } 1.1 root 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: 1.1.1.3 root 4906: KIND is a string distinguishing these three cases ("delay", "annul_true", 1.1 root 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"); 1.1.1.5 root 4931: printf ("eligible_for_%s (delay_insn, slot, candidate_insn, flags)\n", 4932: kind); 1.1 root 4933: printf (" rtx delay_insn;\n"); 4934: printf (" int slot;\n"); 4935: printf (" rtx candidate_insn;\n"); 1.1.1.5 root 4936: printf (" int flags;\n"); 1.1 root 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: { 1.1.1.2 root 4948: attr = find_attr ("*delay_type", 0); 1.1 root 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 1.1.1.4 root 5035: one if there is only one issue delay value. */ 1.1 root 5036: 5037: for (unit = units; unit; unit = unit->next) 5038: { 1.1.1.4 root 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) 1.1 root 5045: { 1.1.1.4 root 5046: unit->default_cost = make_numeric_value (unit->issue_delay.max); 5047: continue; 1.1 root 5048: } 5049: 5050: /* The function first computes the case from the candidate insn. */ 5051: unit->default_cost = make_numeric_value (0); 1.1.1.4 root 5052: write_complex_function (unit, "conflict_cost", "cost"); 5053: } 1.1 root 5054: 1.1.1.4 root 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. */ 1.1 root 5058: 1.1.1.4 root 5059: printf ("struct function_unit_desc function_units[] = {\n"); 1.1 root 5060: 1.1.1.4 root 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; 1.1 root 5068: 1.1.1.4 root 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); 1.1 root 5073: 1.1.1.4 root 5074: if (unit->needs_conflict_function) 5075: printf ("%s_unit_conflict_cost, ", unit->name); 5076: else 5077: printf ("0, "); 1.1 root 5078: 1.1.1.4 root 5079: printf ("%d, ", unit->max_blockage); 1.1 root 5080: 1.1.1.4 root 5081: if (unit->needs_range_function) 5082: printf ("%s_unit_blockage_range, ", unit->name); 5083: else 5084: printf ("0, "); 1.1 root 5085: 1.1.1.4 root 5086: if (unit->needs_blockage_function) 5087: printf ("%s_unit_blockage", unit->name); 5088: else 5089: printf ("0"); 1.1 root 5090: 1.1.1.4 root 5091: printf ("}, \n"); 5092: } 1.1 root 5093: 1.1.1.4 root 5094: printf ("};\n\n"); 5095: } 1.1 root 5096: 1.1.1.4 root 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; 1.1 root 5108: 1.1.1.4 root 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"); 1.1 root 5120: 1.1.1.4 root 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); 1.1 root 5127: 1.1.1.4 root 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++) 1.1 root 5144: { 1.1.1.4 root 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; 1.1 root 5151: 1.1.1.4 root 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) 1.1.1.5 root 5163: write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2, -2); 1.1 root 5164: else 1.1.1.4 root 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); 1.1 root 5174: 1.1.1.4 root 5175: write_attr_case (attr, common_av, 0, 5176: "return", ";", 8, unit->condexp); 5177: printf (" }\n\n"); 5178: } 1.1 root 5179: } 5180: 1.1.1.4 root 5181: printf (" }\n}\n\n"); 1.1 root 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: 1.1.1.2 root 5223: out_str = attr_string (*pstr, p - *pstr); 5224: *pstr = p; 1.1 root 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; 1.1.1.3 root 5241: int index; 1.1 root 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: 1.1.1.3 root 5248: index = name[0] & (MAX_ATTRS_INDEX - 1); 5249: for (attr = attrs[index]; attr; attr = attr->next) 1.1 root 5250: if (name == attr->name) 5251: return attr; 5252: 5253: /* Otherwise, do it the slow way. */ 1.1.1.3 root 5254: for (attr = attrs[index]; attr; attr = attr->next) 5255: if (name[0] == attr->name[0] && ! strcmp (name, attr->name)) 1.1 root 5256: return attr; 5257: 5258: if (! create) 5259: return NULL; 5260: 1.1.1.4 root 5261: attr = (struct attr_desc *) oballoc (sizeof (struct attr_desc)); 1.1.1.3 root 5262: attr->name = attr_string (name, strlen (name)); 1.1 root 5263: attr->first_value = attr->default_val = NULL; 1.1.1.4 root 5264: attr->is_numeric = attr->negative_ok = attr->is_const = attr->is_special = 0; 1.1.1.3 root 5265: attr->next = attrs[index]; 5266: attrs[index] = attr; 1.1 root 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; 1.1.1.2 root 5286: attr->is_const = 0; 1.1.1.4 root 5287: attr->is_special = (special & 1) != 0; 5288: attr->negative_ok = (special & 2) != 0; 5289: attr->unsigned_p = (special & 4) != 0; 1.1 root 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; 1.1.1.2 root 5344: char *p; 1.1 root 5345: 5346: if (n < 0) 5347: abort (); 5348: 5349: if (n < 20 && int_values[n]) 5350: return int_values[n]; 5351: 1.1.1.4 root 5352: p = attr_printf (MAX_DIGITS, "%d", n); 1.1.1.2 root 5353: exp = attr_rtx (CONST_STRING, p); 1.1 root 5354: 5355: if (n < 20) 5356: int_values[n] = exp; 5357: 5358: return exp; 5359: } 5360: 1.1.1.4 root 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: 1.1 root 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: 1.1.1.3 root 5393: static rtx 5394: copy_rtx_unchanging (orig) 5395: register rtx orig; 5396: { 1.1.1.4 root 5397: #if 0 1.1.1.3 root 5398: register rtx copy; 5399: register RTX_CODE code; 1.1.1.4 root 5400: #endif 1.1.1.3 root 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: 1.1 root 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: } 1.1.1.4 root 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"); 1.1.1.5 root 5462: printf (" rtx insn;\n"); 1.1.1.4 root 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: 1.1 root 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; 1.1.1.3 root 5498: int i; 1.1 root 5499: 1.1.1.4 root 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: 1.1 root 5512: obstack_init (rtl_obstack); 1.1.1.3 root 5513: obstack_init (hash_obstack); 5514: obstack_init (temp_obstack); 1.1 root 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 */ 1.1.1.3 root 5529: true_rtx = rtx_alloc (CONST_INT); 1.1.1.4 root 5530: XWINT (true_rtx, 0) = 1; 1.1.1.3 root 5531: false_rtx = rtx_alloc (CONST_INT); 1.1.1.4 root 5532: XWINT (false_rtx, 0) = 0; 1.1 root 5533: RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1; 1.1.1.3 root 5534: RTX_INTEGRATED_P (true_rtx) = RTX_INTEGRATED_P (false_rtx) = 1; 5535: 5536: alternative_name = attr_string ("alternative", strlen ("alternative")); 1.1 root 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'. */ 1.1.1.4 root 5609: insn_alternatives = (int *) oballoc (insn_code_number * sizeof (int)); 1.1 root 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: 1.1.1.3 root 5614: /* Make `insn_n_alternatives'. */ 1.1.1.4 root 5615: insn_n_alternatives = (int *) oballoc (insn_code_number * sizeof (int)); 1.1.1.3 root 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: 1.1 root 5620: /* Prepare to write out attribute subroutines by checking everything stored 5621: away and building the attribute cases. */ 5622: 5623: check_defs (); 1.1.1.3 root 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: } 1.1 root 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: 1.1.1.3 root 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: } 1.1 root 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: 1.1.1.4 root 5665: /* Write out constant delay slot info */ 5666: write_const_num_delay_slots (); 5667: 1.1 root 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.