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