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