|
|
1.1 ! root 1: /* Generate code from machine description to compute values of attributes. ! 2: Copyright (C) 1991 Free Software Foundation, Inc. ! 3: Contributed by Richard Kenner ([email protected]) ! 4: ! 5: This file is part of GNU CC. ! 6: ! 7: GNU CC is free software; you can redistribute it and/or modify ! 8: it under the terms of the GNU General Public License as published by ! 9: the Free Software Foundation; either version 2, or (at your option) ! 10: any later version. ! 11: ! 12: GNU CC is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 15: GNU General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU General Public License ! 18: along with GNU CC; see the file COPYING. If not, write to ! 19: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 20: ! 21: /* This program handles insn attribues and the DEFINE_DELAY and ! 22: DEFINE_FUNCTION_UNIT definitions. ! 23: ! 24: It produces a series of functions call `get_attr_...', one for each ! 25: attribute. Each of these is given the rtx for an insn and returns a member ! 26: of the enum for the attribute. ! 27: ! 28: These subroutines have the form of a `switch' on the INSN_CODE (via ! 29: `recog_memoized'). Each case either returns a constant attribute value ! 30: or a value that depends on tests on other attributes, the form of ! 31: operands, or some random C expression (encoded with a SYMBOL_REF ! 32: expression). ! 33: ! 34: If the attribute `alternative', or a random C expression is present, ! 35: `constrain_operands' is called. If either of these cases of a reference to ! 36: an operand is found, `insn_extract' is called. ! 37: ! 38: The special attribute `length' is also recognized. For this operand, ! 39: expressions involving the address of an operand or the current insn, ! 40: (address (pc)), are valid. In this case, an initial pass is made to ! 41: set all lengths that do not depend on address. Those that do are set to ! 42: the maximum length. Then each insn that depends on an address is checked ! 43: and possibly has its length changed. The process repeats until no further ! 44: changed are made. The resulting lengths are saved for use by ! 45: `get_attr_length'. ! 46: ! 47: Internal attributes are defined to handle DEFINE_DELAY and ! 48: DEFINE_FUNCTION_UNIT. Special routines are output for these cases. ! 49: ! 50: This program works by keeping a list of possible values for each attribute. ! 51: These include the basic attribute choices, default values for attribute, and ! 52: all derived quantities. ! 53: ! 54: As the description file is read, the definition for each insn is saved in a ! 55: `struct insn_def'. When the file reading is complete, a `struct insn_ent' ! 56: is created for each insn and chained to the corresponding attribute value, ! 57: either that specified, or the default. ! 58: ! 59: An optimization phase is then run. This simplifies expressions for each ! 60: insn. EQ_ATTR tests are resolved, whenever possible, to a test that ! 61: indicates when the attribute has the specified value for the insn. This ! 62: avoids recursive calls during compilation. ! 63: ! 64: The strategy used when processing DEFINE_DELAY and DEFINE_FUNCTION_UNIT ! 65: definitions is to create arbitrarily complex expressions and have the ! 66: optimization simplify them. ! 67: ! 68: Once optimization is complete, any required routines and definitions ! 69: will be written. */ ! 70: ! 71: #include <stdio.h> ! 72: #include "config.h" ! 73: #include "rtl.h" ! 74: #include "obstack.h" ! 75: #include "insn-config.h" /* For REGISTER_CONSTRAINTS */ ! 76: ! 77: static struct obstack obstack; ! 78: struct obstack *rtl_obstack = &obstack; ! 79: ! 80: #define obstack_chunk_alloc xmalloc ! 81: #define obstack_chunk_free free ! 82: ! 83: extern void free (); ! 84: ! 85: static void fatal (); ! 86: void fancy_abort (); ! 87: ! 88: /* Define structures used to record attributes and values. */ ! 89: ! 90: /* As each DEFINE_INSN, DEFINE_PEEPHOLE, or DEFINE_ASM_ATTRIBUTES is ! 91: encountered, we store all the relevant information into a ! 92: `struct insn_def'. This is done to allow attribute definitions to occur ! 93: anywhere in the file. */ ! 94: ! 95: struct insn_def ! 96: { ! 97: int insn_code; /* Instruction number. */ ! 98: int insn_index; /* Expression numer in file, for errors. */ ! 99: struct insn_def *next; /* Next insn in chain. */ ! 100: rtx def; /* The DEFINE_... */ ! 101: int num_alternatives; /* Number of alternatives. */ ! 102: int vec_idx; /* Index of attribute vector in `def'. */ ! 103: }; ! 104: ! 105: /* Once everything has been read in, we store in each attribute value a list ! 106: of insn codes that have that value. Here is the structure used for the ! 107: list. */ ! 108: ! 109: struct insn_ent ! 110: { ! 111: int insn_code; /* Instruction number. */ ! 112: int insn_index; /* Index of definition in file */ ! 113: struct insn_ent *next; /* Next in chain. */ ! 114: }; ! 115: ! 116: /* Each value of an attribute (either constant or computed) is assigned a ! 117: structure which is used as the listhead of the insns that have that ! 118: value. */ ! 119: ! 120: struct attr_value ! 121: { ! 122: rtx value; /* Value of attribute. */ ! 123: struct attr_value *next; /* Next attribute value in chain. */ ! 124: struct insn_ent *first_insn; /* First insn with this value. */ ! 125: int num_insns; /* Number of insns with this value. */ ! 126: int has_asm_insn; /* True if this value used for `asm' insns */ ! 127: }; ! 128: ! 129: /* Structure for each attribute. */ ! 130: ! 131: struct attr_desc ! 132: { ! 133: char *name; /* Name of attribute. */ ! 134: struct attr_desc *next; /* Next attribute. */ ! 135: int is_numeric; /* Values of this attribute are numeric. */ ! 136: int is_special; /* Don't call `write_attr_set'. */ ! 137: struct attr_value *first_value; /* First value of this attribute. */ ! 138: struct attr_value *default_val; /* Default value for this attribute. */ ! 139: }; ! 140: ! 141: /* Structure for each DEFINE_DELAY. */ ! 142: ! 143: struct delay_desc ! 144: { ! 145: rtx def; /* DEFINE_DELAY expression. */ ! 146: struct delay_desc *next; /* Next DEFINE_DELAY. */ ! 147: int num; /* Number of DEFINE_DELAY, starting at 1. */ ! 148: }; ! 149: ! 150: /* Record information about each DEFINE_FUNCTION_UNIT. */ ! 151: ! 152: struct function_unit_op ! 153: { ! 154: rtx condexp; /* Expression TRUE for applicable insn. */ ! 155: struct function_unit_op *next; /* Next operation for this function unit. */ ! 156: int num; /* Ordinal for this operation type in unit. */ ! 157: int ready; /* Cost until data is ready. */ ! 158: rtx busyexp; /* Expression computing conflict cost. */ ! 159: }; ! 160: ! 161: /* Record information about each function unit mentioned in a ! 162: DEFINE_FUNCTION_UNIT. */ ! 163: ! 164: struct function_unit ! 165: { ! 166: char *name; /* Function unit name. */ ! 167: struct function_unit *next; /* Next function unit. */ ! 168: int num; /* Ordinal of this unit type. */ ! 169: int multiplicity; /* Number of units of this type. */ ! 170: int simultaneity; /* Maximum number of simultaneous insns ! 171: on this function unit or 0 if unlimited. */ ! 172: rtx condexp; /* Expression TRUE for insn needing unit. */ ! 173: rtx costexp; /* Worst-case cost as function of insn. */ ! 174: int num_opclasses; /* Number of different operation types. */ ! 175: struct function_unit_op *ops; /* Pointer to first operation type. */ ! 176: int needs_conflict_function; /* Nonzero if a conflict function required. */ ! 177: rtx default_cost; /* Conflict cost, if constant. */ ! 178: }; ! 179: ! 180: /* Listheads of above structures. */ ! 181: ! 182: static struct attr_desc *attrs; ! 183: static struct insn_def *defs; ! 184: static struct delay_desc *delays; ! 185: static struct function_unit *units; ! 186: ! 187: /* Other variables. */ ! 188: ! 189: static int insn_code_number; ! 190: static int insn_index_number; ! 191: static int got_define_asm_attributes; ! 192: static int must_extract; ! 193: static int must_constrain; ! 194: static int address_used; ! 195: static int num_delays; ! 196: static int have_annul_true, have_annul_false; ! 197: static int num_units; ! 198: ! 199: /* Used as operand to `operate_exp': */ ! 200: ! 201: enum operator {PLUS_OP, MINUS_OP, OR_OP, MAX_OP}; ! 202: ! 203: /* Stores, for each insn code, a bitmap that has bits on for each possible ! 204: alternative. */ ! 205: ! 206: static int *insn_alternatives; ! 207: ! 208: /* Used to simplify expressions. */ ! 209: ! 210: static rtx true_rtx, false_rtx; ! 211: ! 212: /* Used to reduce calls to `strcmp' */ ! 213: ! 214: static char *alternative_name = "alternative"; ! 215: ! 216: /* Simplify an expression. Only call the routine if there is something to ! 217: simplify. */ ! 218: #define SIMPLIFY_TEST_EXP(EXP,INSN_CODE,INSN_INDEX) \ ! 219: (RTX_UNCHANGING_P (EXP) ? (EXP) \ ! 220: : simplify_test_exp (EXP, INSN_CODE, INSN_INDEX)) ! 221: ! 222: /* These are referenced by rtlanal.c and hence need to be defined somewhere. ! 223: They won't actually be used. */ ! 224: ! 225: rtx frame_pointer_rtx, stack_pointer_rtx, arg_pointer_rtx; ! 226: ! 227: static rtx check_attr_test (); ! 228: static void check_attr_value (); ! 229: static rtx convert_set_attr_alternative (); ! 230: static rtx convert_set_attr (); ! 231: static void check_defs (); ! 232: static rtx make_canonical (); ! 233: static struct attr_value *get_attr_value (); ! 234: static void expand_delays (); ! 235: static rtx operate_exp (); ! 236: static void expand_units (); ! 237: static void fill_attr (); ! 238: static rtx substitute_address (); ! 239: static void make_length_attrs (); ! 240: static rtx identity_fn (); ! 241: static rtx zero_fn (); ! 242: static rtx one_fn (); ! 243: static rtx max_fn (); ! 244: static rtx simplify_cond (); ! 245: static void remove_insn_ent (); ! 246: static void insert_insn_ent (); ! 247: static rtx insert_right_side (); ! 248: static rtx make_alternative_compare (); ! 249: static int compute_alternative_mask (); ! 250: static rtx evaluate_eq_attr (); ! 251: static rtx simplify_and_tree (); ! 252: static rtx simplify_or_tree (); ! 253: static rtx simplify_test_exp (); ! 254: static void optimize_attrs (); ! 255: static void gen_attr (); ! 256: static int count_alternatives (); ! 257: static int compares_alternatives_p (); ! 258: static int contained_in_p (); ! 259: static void gen_insn (); ! 260: static void gen_delay (); ! 261: static void gen_unit (); ! 262: static void write_test_expr (); ! 263: static int max_attr_value (); ! 264: static void walk_attr_value (); ! 265: static void write_attr_get (); ! 266: static rtx eliminate_known_true (); ! 267: static void write_attr_set (); ! 268: static void write_attr_case (); ! 269: static void write_attr_value (); ! 270: static void write_attr_valueq (); ! 271: static void write_upcase (); ! 272: static void write_indent (); ! 273: static void write_eligible_delay (); ! 274: static void write_function_unit_info (); ! 275: static int n_comma_elts (); ! 276: static char *next_comma_elt (); ! 277: static struct attr_desc *find_attr (); ! 278: static void make_internal_attr (); ! 279: static struct attr_value *find_most_used (); ! 280: static rtx find_single_value (); ! 281: static rtx make_numeric_value (); ! 282: char *xrealloc (); ! 283: char *xmalloc (); ! 284: static void fatal (); ! 285: ! 286: /* Given a test expression for an attribute, ensure it is validly formed. ! 287: Convert (eq_attr "att" "a1,a2") to (ior (eq_attr ... ) (eq_attrq ..)) ! 288: and (eq_attr "att" "!a1") to (not (eq_attr "att" "a1")). Do the latter ! 289: test first so that (eq_attr "att" "!a1,a2,a3") works as expected. ! 290: ! 291: Update the string address in EQ_ATTR expression to be the same used ! 292: in the attribute (or `alternative_name') to speed up subsequent ! 293: `find_attr' calls and eliminate most `strcmp' calls. ! 294: ! 295: Return the new expression, if any. */ ! 296: ! 297: static rtx ! 298: check_attr_test (exp) ! 299: rtx exp; ! 300: { ! 301: struct attr_desc *attr; ! 302: struct attr_value *av; ! 303: char *name_ptr, *p; ! 304: rtx orexp, newexp; ! 305: ! 306: switch (GET_CODE (exp)) ! 307: { ! 308: case EQ_ATTR: ! 309: /* Handle negation test. */ ! 310: if (XSTR (exp, 1)[0] == '!') ! 311: { ! 312: XSTR(exp, 1) = &XSTR(exp, 1)[1]; ! 313: newexp = rtx_alloc (NOT); ! 314: XEXP (newexp, 0) = exp; ! 315: ! 316: return check_attr_test (newexp); ! 317: } ! 318: ! 319: else if (n_comma_elts (XSTR (exp, 1)) == 1) ! 320: { ! 321: attr = find_attr (XEXP (exp, 0), 0); ! 322: if (attr == NULL) ! 323: { ! 324: if (! strcmp (XSTR (exp, 0), "alternative")) ! 325: { ! 326: XSTR (exp, 0) = alternative_name; ! 327: /* This can't be simplified any further. */ ! 328: RTX_UNCHANGING_P (exp) = 1; ! 329: return exp; ! 330: } ! 331: else ! 332: fatal ("Unknown attribute `%s' in EQ_ATTR", XEXP (exp, 0)); ! 333: } ! 334: ! 335: XSTR (exp, 0) = attr->name; ! 336: ! 337: if (attr->is_numeric) ! 338: { ! 339: for (p = XSTR (exp, 1); *p; p++) ! 340: if (*p < '0' || *p > '9') ! 341: fatal ("Attribute `%s' takes only numeric values", ! 342: XEXP (exp, 0)); ! 343: } ! 344: else ! 345: { ! 346: for (av = attr->first_value; av; av = av->next) ! 347: if (GET_CODE (av->value) == CONST_STRING ! 348: && ! strcmp (XSTR (exp, 1), XSTR (av->value, 0))) ! 349: break; ! 350: ! 351: if (av == NULL) ! 352: fatal ("Unknown value `%s' for `%s' attribute", ! 353: XEXP (exp, 1), XEXP (exp, 0)); ! 354: } ! 355: } ! 356: else ! 357: { ! 358: /* Make an IOR tree of the possible values. */ ! 359: orexp = false_rtx; ! 360: name_ptr = XSTR (exp, 1); ! 361: while ((p = next_comma_elt (&name_ptr)) != NULL) ! 362: { ! 363: newexp = rtx_alloc (EQ_ATTR); ! 364: XSTR (newexp, 0) = XSTR (exp, 0); ! 365: XSTR (newexp, 1) = p; ! 366: orexp = insert_right_side (IOR, orexp, newexp, -2); ! 367: } ! 368: ! 369: return check_attr_test (orexp); ! 370: } ! 371: break; ! 372: ! 373: case CONST_INT: ! 374: /* Either TRUE or FALSE. */ ! 375: if (XINT (exp, 0)) ! 376: return true_rtx; ! 377: else ! 378: return false_rtx; ! 379: ! 380: case IOR: ! 381: case AND: ! 382: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0)); ! 383: XEXP (exp, 1) = check_attr_test (XEXP (exp, 1)); ! 384: break; ! 385: ! 386: case NOT: ! 387: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0)); ! 388: break; ! 389: ! 390: case MATCH_OPERAND: ! 391: case LE: case LT: case GT: case GE: ! 392: case LEU: case LTU: case GTU: case GEU: ! 393: case NE: case EQ: ! 394: /* These cases can't be simplified. */ ! 395: RTX_UNCHANGING_P (exp) = 1; ! 396: break; ! 397: ! 398: default: ! 399: fatal ("RTL operator \"%s\" not valid in attribute test", ! 400: GET_RTX_NAME (GET_CODE (exp))); ! 401: } ! 402: ! 403: return exp; ! 404: } ! 405: ! 406: /* Given an expression, ensure that it is validly formed and that all named ! 407: attribute values are valid for the given attribute. Issue a fatal error ! 408: if not. If no attribute is specified, assume a numeric attribute. */ ! 409: ! 410: static void ! 411: check_attr_value (exp, attr) ! 412: rtx exp; ! 413: struct attr_desc *attr; ! 414: { ! 415: struct attr_value *av; ! 416: char *p; ! 417: int i; ! 418: ! 419: switch (GET_CODE (exp)) ! 420: { ! 421: case CONST_INT: ! 422: if (attr && ! attr->is_numeric) ! 423: fatal ("CONST_INT not valid for non-numeric `%s' attribute", ! 424: attr->name); ! 425: ! 426: if (INTVAL (exp) < 0) ! 427: fatal ("Negative numeric value specified for `%s' attribute", ! 428: attr->name); ! 429: ! 430: break; ! 431: ! 432: case CONST_STRING: ! 433: if (! strcmp (XSTR (exp, 0), "*")) ! 434: break; ! 435: ! 436: if (attr == 0 || attr->is_numeric) ! 437: { ! 438: for (p = XSTR (exp, 0); *p; p++) ! 439: if (*p > '9' || *p < '0') ! 440: fatal ("Non-numeric value for numeric `%s' attribute", ! 441: attr ? "internal" : attr->name); ! 442: break; ! 443: } ! 444: ! 445: for (av = attr->first_value; av; av = av->next) ! 446: if (GET_CODE (av->value) == CONST_STRING ! 447: && ! strcmp (XSTR (av->value, 0), XSTR (exp, 0))) ! 448: break; ! 449: ! 450: if (av == NULL) ! 451: fatal ("Unknown value `%s' for `%s' attribute", ! 452: XSTR (exp, 0), attr ? "internal" : attr->name); ! 453: ! 454: return; ! 455: ! 456: case IF_THEN_ELSE: ! 457: XEXP (exp, 0) = check_attr_test (XEXP (exp, 0)); ! 458: check_attr_value (XEXP (exp, 1), attr); ! 459: check_attr_value (XEXP (exp, 2), attr); ! 460: return; ! 461: ! 462: case COND: ! 463: if (XVECLEN (exp, 0) % 2 != 0) ! 464: fatal ("First operand of COND must have even length"); ! 465: ! 466: for (i = 0; i < XVECLEN (exp, 0); i += 2) ! 467: { ! 468: XVECEXP (exp, 0, i) = check_attr_test (XVECEXP (exp, 0, i)); ! 469: check_attr_value (XVECEXP (exp, 0, i + 1), attr); ! 470: } ! 471: ! 472: check_attr_value (XEXP (exp, 1), attr); ! 473: return; ! 474: ! 475: default: ! 476: fatal ("Illegal operation `%s' for attribute value", ! 477: GET_RTX_NAME (GET_CODE (exp))); ! 478: } ! 479: } ! 480: ! 481: /* Given an SET_ATTR_ALTERNATIVE expression, convert to the canonical SET. ! 482: It becomes a COND with each test being (eq_attr "alternative "n") */ ! 483: ! 484: static rtx ! 485: convert_set_attr_alternative (exp, num_alt, insn_code, insn_index) ! 486: rtx exp; ! 487: int num_alt; ! 488: int insn_code, insn_index; ! 489: { ! 490: rtx newexp; ! 491: rtx condexp; ! 492: int i; ! 493: ! 494: if (XVECLEN (exp, 1) != num_alt) ! 495: fatal ("Bad number of entries in SET_ATTR_ALTERNATIVE for insn %d", ! 496: insn_index); ! 497: ! 498: /* Make a COND with all tests but the last. Select the last value via the ! 499: default. */ ! 500: condexp = rtx_alloc (COND); ! 501: XVEC (condexp, 0) = rtvec_alloc ((num_alt - 1) * 2); ! 502: ! 503: for (i = 0; i < num_alt - 1; i++) ! 504: { ! 505: XVECEXP (condexp, 0, 2 * i) = rtx_alloc (EQ_ATTR); ! 506: XSTR (XVECEXP (condexp, 0, 2 * i), 0) = alternative_name; ! 507: XSTR (XVECEXP (condexp, 0, 2 * i), 1) = (char *) xmalloc (3); ! 508: sprintf (XSTR (XVECEXP (condexp, 0, 2 * i), 1), "%d", i); ! 509: XVECEXP (condexp, 0, 2 * i + 1) = XVECEXP (exp, 1, i); ! 510: } ! 511: ! 512: XEXP (condexp, 1) = XVECEXP (exp, 1, i); ! 513: ! 514: newexp = rtx_alloc (SET); ! 515: XEXP (newexp, 0) = rtx_alloc (ATTR); ! 516: XSTR (XEXP (newexp, 0), 0) = XSTR (exp, 0); ! 517: XEXP (newexp, 1) = condexp; ! 518: ! 519: return newexp; ! 520: } ! 521: ! 522: /* Given a SET_ATTR, convert to the appropriate SET. If a comma-separated ! 523: list of values is given, convert to SET_ATTR_ALTERNATIVE first. */ ! 524: ! 525: static rtx ! 526: convert_set_attr (exp, num_alt, insn_code, insn_index) ! 527: rtx exp; ! 528: int num_alt; ! 529: int insn_code, insn_index; ! 530: { ! 531: rtx newexp; ! 532: char *name_ptr; ! 533: char *p; ! 534: int n; ! 535: ! 536: /* See how many alternative specified. */ ! 537: n = n_comma_elts (XSTR (exp, 1)); ! 538: if (n == 1) ! 539: { ! 540: newexp = rtx_alloc (SET); ! 541: XEXP (newexp, 0) = rtx_alloc (ATTR); ! 542: XSTR (XEXP (newexp, 0), 0) = XSTR (exp, 0); ! 543: XEXP (newexp, 1) = rtx_alloc (CONST_STRING); ! 544: XSTR (XEXP (newexp, 1), 0) = XSTR (exp, 1); ! 545: ! 546: return newexp; ! 547: } ! 548: ! 549: newexp = rtx_alloc (SET_ATTR_ALTERNATIVE); ! 550: XSTR (newexp, 0) = XSTR (exp, 0); ! 551: XVEC (newexp, 1) = rtvec_alloc (n); ! 552: ! 553: /* Process each comma-separated name. */ ! 554: name_ptr = XSTR (exp, 1); ! 555: n = 0; ! 556: while ((p = next_comma_elt (&name_ptr)) != NULL) ! 557: { ! 558: XVECEXP (newexp, 1, n) = rtx_alloc (CONST_STRING); ! 559: XSTR (XVECEXP (newexp, 1, n++), 0) = p; ! 560: } ! 561: ! 562: return convert_set_attr_alternative (newexp, num_alt, insn_code, insn_index); ! 563: } ! 564: ! 565: /* Scan all definitions, checking for validity. Also, convert any SET_ATTR ! 566: and SET_ATTR_ALTERNATIVE expressions to the corresponding SET ! 567: expressions. */ ! 568: ! 569: static void ! 570: check_defs () ! 571: { ! 572: struct insn_def *id; ! 573: struct attr_desc *attr; ! 574: int i; ! 575: rtx value; ! 576: ! 577: for (id = defs; id; id = id->next) ! 578: { ! 579: if (XVEC (id->def, id->vec_idx) == NULL) ! 580: continue; ! 581: ! 582: for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++) ! 583: { ! 584: value = XVECEXP (id->def, id->vec_idx, i); ! 585: switch (GET_CODE (value)) ! 586: { ! 587: case SET: ! 588: if (GET_CODE (XEXP (value, 0)) != ATTR) ! 589: fatal ("Bad attribute set in pattern %d", id->insn_index); ! 590: break; ! 591: ! 592: case SET_ATTR_ALTERNATIVE: ! 593: value = convert_set_attr_alternative (value, ! 594: id->num_alternatives, ! 595: id->insn_code, ! 596: id->insn_index); ! 597: break; ! 598: ! 599: case SET_ATTR: ! 600: value = convert_set_attr (value, id->num_alternatives, ! 601: id->insn_code, id->insn_index); ! 602: break; ! 603: ! 604: default: ! 605: fatal ("Invalid attribute code `%s' for pattern %d", ! 606: GET_RTX_NAME (GET_CODE (value)), id->insn_index); ! 607: } ! 608: ! 609: if ((attr = find_attr (XSTR (XEXP (value, 0), 0), 0)) == NULL) ! 610: fatal ("Unknown attribute `%s' for pattern number %d", ! 611: XSTR (XEXP (value, 0), 0), id->insn_index); ! 612: ! 613: XVECEXP (id->def, id->vec_idx, i) = value; ! 614: check_attr_value (XEXP (value, 1), attr); ! 615: } ! 616: } ! 617: } ! 618: ! 619: /* Given a valid expression for an attribute value, remove any IF_THEN_ELSE ! 620: expressions by converting them into a COND. This removes cases from this ! 621: program. Also, replace an attribute value of "*" with the default attribute ! 622: value. */ ! 623: ! 624: static rtx ! 625: make_canonical (attr, exp) ! 626: struct attr_desc *attr; ! 627: rtx exp; ! 628: { ! 629: int i; ! 630: rtx newexp; ! 631: ! 632: switch (GET_CODE (exp)) ! 633: { ! 634: case CONST_INT: ! 635: exp = make_numeric_value (INTVAL (exp)); ! 636: break; ! 637: ! 638: case CONST_STRING: ! 639: if (! strcmp (XSTR (exp, 0), "*")) ! 640: { ! 641: if (attr == 0 || attr->default_val == 0) ! 642: fatal ("(attr_value \"*\") used in invalid context."); ! 643: exp = attr->default_val->value; ! 644: } ! 645: ! 646: break; ! 647: ! 648: case IF_THEN_ELSE: ! 649: newexp = rtx_alloc (COND); ! 650: XVEC (newexp, 0) = rtvec_alloc (2); ! 651: XVECEXP (newexp, 0, 0) = XEXP (exp, 0); ! 652: XVECEXP (newexp, 0, 1) = XEXP (exp, 1); ! 653: ! 654: XEXP (newexp, 1) = XEXP (exp, 2); ! 655: ! 656: exp = newexp; ! 657: /* Fall through to COND case since this is now a COND. */ ! 658: ! 659: case COND: ! 660: /* First, check for degenerate COND. */ ! 661: if (XVECLEN (exp, 0) == 0) ! 662: return make_canonical (attr, XEXP (exp, 1)); ! 663: ! 664: for (i = 0; i < XVECLEN (exp, 0); i += 2) ! 665: XVECEXP (exp, 0, i + 1) ! 666: = make_canonical (attr, XVECEXP (exp, 0, i + 1)); ! 667: ! 668: XEXP (exp, 1) = make_canonical (attr, XEXP (exp, 1)); ! 669: break; ! 670: } ! 671: ! 672: return exp; ! 673: } ! 674: ! 675: /* Given a value and an attribute description, return a `struct attr_value *' ! 676: that represents that value. This is either an existing structure, if the ! 677: value has been previously encountered, or a newly-created structure. ! 678: ! 679: `insn_code' is the code of an insn whose attribute has the specified ! 680: value (-2 if not processing an insn). We ensure that all insns for ! 681: a given value have the same number of alternatives if the value checks ! 682: alternatives. */ ! 683: ! 684: static struct attr_value * ! 685: get_attr_value (value, attr, insn_code) ! 686: rtx value; ! 687: struct attr_desc *attr; ! 688: int insn_code; ! 689: { ! 690: struct attr_value *av; ! 691: int num_alt = 0; ! 692: ! 693: value = make_canonical (attr, value); ! 694: if (compares_alternatives_p (value)) ! 695: { ! 696: if (insn_code < 0 || insn_alternatives == NULL) ! 697: fatal ("(eq_attr \"alternatives\" ...) used in non-insn context"); ! 698: else ! 699: num_alt = insn_alternatives[insn_code]; ! 700: } ! 701: ! 702: for (av = attr->first_value; av; av = av->next) ! 703: if (rtx_equal_p (value, av->value) ! 704: && (num_alt == 0 || av->first_insn == NULL ! 705: || insn_alternatives[av->first_insn->insn_code])) ! 706: return av; ! 707: ! 708: av = (struct attr_value *) xmalloc (sizeof (struct attr_value)); ! 709: av->value = value; ! 710: av->next = attr->first_value; ! 711: attr->first_value = av; ! 712: av->first_insn = NULL; ! 713: av->num_insns = 0; ! 714: av->has_asm_insn = 0; ! 715: ! 716: return av; ! 717: } ! 718: ! 719: /* After all DEFINE_DELAYs have been read in, create internal attributes ! 720: to generate the required routines. ! 721: ! 722: First, we compute the number of delay slots for each insn (as a COND of ! 723: each of the test expressions in DEFINE_DELAYs). Then, if more than one ! 724: delay type is specified, we compute a similar function giving the ! 725: DEFINE_DELAY ordinal for each insn. ! 726: ! 727: Finally, for each [DEFINE_DELAY, slot #] pair, we compute an attribute that ! 728: tells whether a given insn can be in that delay slot. ! 729: ! 730: Normal attrbute filling and optimization expands these to contain the ! 731: information needed to handle delay slots. */ ! 732: ! 733: static void ! 734: expand_delays () ! 735: { ! 736: struct delay_desc *delay; ! 737: rtx condexp; ! 738: rtx newexp; ! 739: int i; ! 740: char *p; ! 741: ! 742: /* First, generate data for `num_delay_slots' function. */ ! 743: ! 744: condexp = rtx_alloc (COND); ! 745: XVEC (condexp, 0) = rtvec_alloc (num_delays * 2); ! 746: XEXP (condexp, 1) = make_numeric_value (0); ! 747: ! 748: for (i = 0, delay = delays; delay; i += 2, delay = delay->next) ! 749: { ! 750: XVECEXP (condexp, 0, i) = XEXP (delay->def, 0); ! 751: XVECEXP (condexp, 0, i + 1) ! 752: = make_numeric_value (XVECLEN (delay->def, 1) / 3); ! 753: } ! 754: ! 755: make_internal_attr ("*num_delay_slots", condexp, 0); ! 756: ! 757: /* If more than one delay type, do the same for computing the delay type. */ ! 758: if (num_delays > 1) ! 759: { ! 760: condexp = rtx_alloc (COND); ! 761: XVEC (condexp, 0) = rtvec_alloc (num_delays * 2); ! 762: XEXP (condexp, 1) = make_numeric_value (0); ! 763: ! 764: for (i = 0, delay = delays; delay; i += 2, delay = delay->next) ! 765: { ! 766: XVECEXP (condexp, 0, i) = XEXP (delay->def, 0); ! 767: XVECEXP (condexp, 0, i + 1) = make_numeric_value (delay->num); ! 768: } ! 769: ! 770: make_internal_attr ("*delay_type", condexp, 1); ! 771: } ! 772: ! 773: /* For each delay possibility and delay slot, compute an eligability ! 774: attribute for non-anulled insns and for each type of annulled (annul ! 775: if true and annul if false). */ ! 776: for (delay = delays; delay; delay = delay->next) ! 777: { ! 778: for (i = 0; i < XVECLEN (delay->def, 1); i += 3) ! 779: { ! 780: newexp = rtx_alloc (IF_THEN_ELSE); ! 781: condexp = XVECEXP (delay->def, 1, i); ! 782: if (condexp == 0) condexp = false_rtx; ! 783: XEXP (newexp, 0) = condexp; ! 784: XEXP (newexp, 1) = make_numeric_value (1); ! 785: XEXP (newexp, 2) = make_numeric_value (0); ! 786: ! 787: p = (char *) xmalloc (13); ! 788: sprintf (p, "*delay_%d_%d", delay->num, i / 3); ! 789: make_internal_attr (p, newexp, 1); ! 790: ! 791: if (have_annul_true) ! 792: { ! 793: newexp = rtx_alloc (IF_THEN_ELSE); ! 794: condexp = XVECEXP (delay->def, 1, i + 1); ! 795: if (condexp == 0) condexp = false_rtx; ! 796: XEXP (newexp, 0) = condexp; ! 797: XEXP (newexp, 1) = make_numeric_value (1); ! 798: XEXP (newexp, 2) = make_numeric_value (0); ! 799: p = (char *) xmalloc (18); ! 800: sprintf (p, "*annul_true_%d_%d", delay->num, i / 3); ! 801: make_internal_attr (p, newexp, 1); ! 802: } ! 803: ! 804: if (have_annul_false) ! 805: { ! 806: newexp = rtx_alloc (IF_THEN_ELSE); ! 807: condexp = XVECEXP (delay->def, 1, i + 2); ! 808: if (condexp == 0) condexp = false_rtx; ! 809: XEXP (newexp, 0) = condexp; ! 810: XEXP (newexp, 1) = make_numeric_value (1); ! 811: XEXP (newexp, 2) = make_numeric_value (0); ! 812: p = (char *) xmalloc (18); ! 813: sprintf (p, "*annul_false_%d_%d", delay->num, i / 3); ! 814: make_internal_attr (p, newexp, 1); ! 815: } ! 816: } ! 817: } ! 818: } ! 819: ! 820: /* This function is given a left and right side expression and an operator. ! 821: Each side is a conditional expression, each alternative of which has a ! 822: numerical value. The function returns another conditional expression ! 823: which, for every possible set of condition values, returns a value that is ! 824: the operator applied to the values of the two sides. ! 825: ! 826: Since this is called early, it must also support IF_THEN_ELSE. */ ! 827: ! 828: static rtx ! 829: operate_exp (op, left, right) ! 830: enum operator op; ! 831: rtx left, right; ! 832: { ! 833: int left_value, right_value; ! 834: rtx newexp; ! 835: int i; ! 836: ! 837: /* If left is a string, apply operator to it and the right side. */ ! 838: if (GET_CODE (left) == CONST_STRING) ! 839: { ! 840: /* If right is also a string, just perform the operation. */ ! 841: if (GET_CODE (right) == CONST_STRING) ! 842: { ! 843: left_value = atoi (XSTR (left, 0)); ! 844: right_value = atoi (XSTR (right, 0)); ! 845: switch (op) ! 846: { ! 847: case PLUS_OP: ! 848: i = left_value + right_value; ! 849: break; ! 850: ! 851: case MINUS_OP: ! 852: i = left_value - right_value; ! 853: break; ! 854: ! 855: case OR_OP: ! 856: i = left_value | right_value; ! 857: break; ! 858: ! 859: case MAX_OP: ! 860: if (left_value > right_value) ! 861: i = left_value; ! 862: else ! 863: i = right_value; ! 864: break; ! 865: ! 866: default: ! 867: abort (); ! 868: } ! 869: ! 870: return make_numeric_value (i); ! 871: } ! 872: else if (GET_CODE (right) == IF_THEN_ELSE) ! 873: { ! 874: /* Apply recursively to all values within. */ ! 875: newexp = rtx_alloc (IF_THEN_ELSE); ! 876: XEXP (newexp, 0) = XEXP (right, 0); ! 877: XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1)); ! 878: XEXP (newexp, 2) = operate_exp (op, left, XEXP (right, 2)); ! 879: ! 880: return newexp; ! 881: } ! 882: else if (GET_CODE (right) == COND) ! 883: { ! 884: newexp = rtx_alloc (COND); ! 885: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (right, 0)); ! 886: for (i = 0; i < XVECLEN (right, 0); i += 2) ! 887: { ! 888: XVECEXP (newexp, 0, i) = XVECEXP (right, 0, i); ! 889: XVECEXP (newexp, 0, i + 1) ! 890: = operate_exp (op, left, XVECEXP (right, 0, i + 1)); ! 891: } ! 892: ! 893: XEXP (newexp, 1) = operate_exp (op, left, XEXP (right, 1)); ! 894: ! 895: return newexp; ! 896: } ! 897: else ! 898: fatal ("Badly formed attribute value"); ! 899: } ! 900: ! 901: /* Otherwise, do recursion the other way. */ ! 902: else if (GET_CODE (left) == IF_THEN_ELSE) ! 903: { ! 904: newexp = rtx_alloc (IF_THEN_ELSE); ! 905: XEXP (newexp, 0) = XEXP (left, 0); ! 906: XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right); ! 907: XEXP (newexp, 2) = operate_exp (op, XEXP (left, 2), right); ! 908: ! 909: return newexp; ! 910: } ! 911: ! 912: else if (GET_CODE (left) == COND) ! 913: { ! 914: newexp = rtx_alloc (COND); ! 915: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (left, 0)); ! 916: for (i = 0; i < XVECLEN (left, 0); i += 2) ! 917: { ! 918: XVECEXP (newexp, 0, i) = XVECEXP (left, 0, i); ! 919: XVECEXP (newexp, 0, i + 1) ! 920: = operate_exp (op, XVECEXP (left, 0, i + 1), right); ! 921: } ! 922: ! 923: XEXP (newexp, 1) = operate_exp (op, XEXP (left, 1), right); ! 924: ! 925: return newexp; ! 926: } ! 927: ! 928: else ! 929: fatal ("Badly formed attribute value."); ! 930: /* NOTREACHED */ ! 931: return NULL; ! 932: } ! 933: ! 934: /* Once all attributes and DEFINE_FUNCTION_UNITs have been read, we ! 935: construct a number of attributes. ! 936: ! 937: The first produces a function `function_units_used' which is given an ! 938: insn and produces a mask showing which function units are required for ! 939: the execution of that insn. ! 940: ! 941: The second produces a function `result_ready_cost' which is used to ! 942: determine the time that the result of an insn will be ready and hence ! 943: a worst-case schedule. ! 944: ! 945: Both of these produce quite complex expressions which are then set as the ! 946: default value of internal attributes. Normal attribute simplification ! 947: should produce reasonable expressions. ! 948: ! 949: For each unit, a `<name>_unit_ready_cost' function will take an ! 950: insn and give the delay until that unit will be ready with the result ! 951: and a `<name>_unit_busy_delay' function is given an insn already ! 952: executing on the unit and a candidate to execute and will give the ! 953: cost from the time the executing insn started until the candidate ! 954: can start (ignore limitations on the number of simultaneous insns). */ ! 955: ! 956: static void ! 957: expand_units () ! 958: { ! 959: struct function_unit *unit; ! 960: struct function_unit_op *op; ! 961: rtx unitsmask; ! 962: rtx readycost; ! 963: rtx newexp; ! 964: char *str; ! 965: ! 966: /* Initially, cost and masks are zero. */ ! 967: unitsmask = readycost = make_numeric_value (0); ! 968: ! 969: /* Set up a conditional for costs and unit mask. */ ! 970: newexp = rtx_alloc (IF_THEN_ELSE); ! 971: XEXP (newexp, 2) = make_numeric_value (0); ! 972: ! 973: /* For each unit, insert its contribution to the above three values. */ ! 974: for (unit = units; unit; unit = unit->next) ! 975: { ! 976: /* An expression that computes the ready cost for this unit. */ ! 977: rtx readyexp = rtx_alloc (COND); ! 978: /* An expression that maps insns to operation number for conflicts. */ ! 979: rtx caseexp = rtx_alloc (COND); ! 980: ! 981: XVEC (readyexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); ! 982: XVEC (caseexp, 0) = rtvec_alloc ((unit->num_opclasses - 1) * 2); ! 983: ! 984: for (op = unit->ops; op; op = op->next) ! 985: { ! 986: str = (char *) xmalloc (strlen (unit->name) + 11); ! 987: ! 988: /* Validate the expressions we were given for the conditions ! 989: and busy cost. Then make an attribute for use in the conflict ! 990: function. */ ! 991: op->condexp = check_attr_test (op->condexp); ! 992: check_attr_value (op->busyexp, 0); ! 993: sprintf (str, "*%s_case_%d", unit->name, op->num); ! 994: make_internal_attr (str, make_canonical (0, op->busyexp)); ! 995: ! 996: /* Make our adjustment to the two COND's being computed. If we are ! 997: the last operation class, place our values into the default of ! 998: the COND. */ ! 999: if (op->num == unit->num_opclasses - 1) ! 1000: { ! 1001: XEXP (readyexp, 1) = make_numeric_value (op->ready); ! 1002: XEXP (caseexp, 1) = make_numeric_value (op->num); ! 1003: } ! 1004: else ! 1005: { ! 1006: XVECEXP (readyexp, 0, op->num * 2) = op->condexp; ! 1007: XVECEXP (readyexp, 0, op->num * 2 + 1) ! 1008: = make_numeric_value (op->ready); ! 1009: XVECEXP (caseexp, 0, op->num * 2) = op->condexp; ! 1010: XVECEXP (caseexp, 0, op->num * 2 + 1) ! 1011: = make_numeric_value (op->num); ! 1012: } ! 1013: } ! 1014: ! 1015: /* Make an attribute for the case number and ready delay. */ ! 1016: str = (char *) xmalloc (strlen (unit->name) + 8); ! 1017: sprintf (str, "*%s_cases", unit->name); ! 1018: make_internal_attr (str, caseexp, 1); ! 1019: ! 1020: str = (char *) xmalloc (strlen (unit->name) + 20); ! 1021: sprintf (str, "*%s_unit_ready_cost", unit->name); ! 1022: make_internal_attr (str, readyexp, 0); ! 1023: ! 1024: /* Merge this function unit into the ready cost and unit mask ! 1025: attributes. */ ! 1026: XEXP (newexp, 0) = check_attr_test (unit->condexp); ! 1027: XEXP (newexp, 1) = make_numeric_value (1 << unit->num); ! 1028: unitsmask = operate_exp (OR_OP, unitsmask, newexp); ! 1029: ! 1030: XEXP (newexp, 1) = readyexp; ! 1031: readycost = operate_exp (MAX_OP, readycost, newexp); ! 1032: } ! 1033: ! 1034: make_internal_attr ("*function_units_used", unitsmask, 0); ! 1035: make_internal_attr ("*result_ready_cost", readycost, 0); ! 1036: } ! 1037: ! 1038: /* Once all attributes and insns have been read and checked, we construct for ! 1039: each attribute value a list of all the insns that have that value for ! 1040: the attribute. */ ! 1041: ! 1042: static void ! 1043: fill_attr (attr) ! 1044: struct attr_desc *attr; ! 1045: { ! 1046: struct attr_value *av; ! 1047: struct insn_ent *ie; ! 1048: struct insn_def *id; ! 1049: int i; ! 1050: rtx value; ! 1051: ! 1052: for (id = defs; id; id = id->next) ! 1053: { ! 1054: /* If no value is specified for this insn for this attribute, use the ! 1055: default. */ ! 1056: value = NULL; ! 1057: if (XVEC (id->def, id->vec_idx)) ! 1058: for (i = 0; i < XVECLEN (id->def, id->vec_idx); i++) ! 1059: if (! strcmp (XSTR (XEXP (XVECEXP (id->def, id->vec_idx, i), 0), 0), ! 1060: attr->name)) ! 1061: value = XEXP (XVECEXP (id->def, id->vec_idx, i), 1); ! 1062: ! 1063: if (value == NULL) ! 1064: av = attr->default_val; ! 1065: else ! 1066: av = get_attr_value (value, attr, id->insn_code); ! 1067: ! 1068: ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent)); ! 1069: ie->insn_code = id->insn_code; ! 1070: ie->insn_index = id->insn_code; ! 1071: insert_insn_ent (av, ie); ! 1072: } ! 1073: } ! 1074: ! 1075: /* Given an expression EXP, see if it is a COND or IF_THEN_ELSE that has a ! 1076: test that checks relative positions of insns (uses MATCH_DUP or PC). ! 1077: If so, replace it with what is obtained by passing the expression to ! 1078: ADDRESS_FN. If not but it is a COND or IF_THEN_ELSE, call this routine ! 1079: recursively on each value (including the default value). Otherwise, ! 1080: return the value returned by NO_ADDRESS_FN applied to EXP. */ ! 1081: ! 1082: static rtx ! 1083: substitute_address (exp, no_address_fn, address_fn) ! 1084: rtx exp; ! 1085: rtx (*no_address_fn) (); ! 1086: rtx (*address_fn) (); ! 1087: { ! 1088: int i; ! 1089: rtx newexp; ! 1090: ! 1091: if (GET_CODE (exp) == COND) ! 1092: { ! 1093: /* See if any tests use addresses. */ ! 1094: address_used = 0; ! 1095: for (i = 0; i < XVECLEN (exp, 0); i += 2) ! 1096: walk_attr_value (XVECEXP (exp, 0, i)); ! 1097: ! 1098: if (address_used) ! 1099: return (*address_fn) (exp); ! 1100: ! 1101: /* Make a new copy of this COND, replacing each element. */ ! 1102: newexp = rtx_alloc (COND); ! 1103: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0)); ! 1104: for (i = 0; i < XVECLEN (exp, 0); i += 2) ! 1105: { ! 1106: XVECEXP (newexp, 0, i) = XVECEXP (exp, 0, i); ! 1107: XVECEXP (newexp, 0, i + 1) ! 1108: = substitute_address (XVECEXP (exp, 0, i + 1), ! 1109: no_address_fn, address_fn); ! 1110: } ! 1111: ! 1112: XEXP (newexp, 1) = substitute_address (XEXP (exp, 1), ! 1113: no_address_fn, address_fn); ! 1114: ! 1115: return newexp; ! 1116: } ! 1117: ! 1118: else if (GET_CODE (exp) == IF_THEN_ELSE) ! 1119: { ! 1120: address_used = 0; ! 1121: walk_attr_value (XEXP (exp, 0)); ! 1122: if (address_used) ! 1123: return (*address_fn) (exp); ! 1124: ! 1125: newexp = rtx_alloc (IF_THEN_ELSE); ! 1126: XEXP (newexp, 0) = substitute_address (XEXP (exp, 0), ! 1127: no_address_fn, address_fn); ! 1128: XEXP (newexp, 1) = substitute_address (XEXP (exp, 1), ! 1129: no_address_fn, address_fn); ! 1130: XEXP (newexp, 2) = substitute_address (XEXP (exp, 2), ! 1131: no_address_fn, address_fn); ! 1132: ! 1133: return newexp; ! 1134: } ! 1135: ! 1136: return (*no_address_fn) (exp); ! 1137: } ! 1138: ! 1139: /* Make new attributes from the `length' attribute. The following are made, ! 1140: each corresponding to a function called from `shorten_branches' or ! 1141: `get_attr_length': ! 1142: ! 1143: *insn_default_length This is the length of the insn to be returned ! 1144: by `get_attr_length' before `shorten_branches' ! 1145: has been called. In each case where the length ! 1146: depends on relative addresses, the largest ! 1147: possible is used. This routine is also used ! 1148: to compute the initial size of the insn. ! 1149: ! 1150: *insn_variable_length_p This returns 1 if the insn's length depends ! 1151: on relative addresses, zero otherwise. ! 1152: ! 1153: *insn_current_length This is only called when it is known that the ! 1154: insn has a variable length and returns the ! 1155: current length, based on relative addresses. ! 1156: */ ! 1157: ! 1158: static void ! 1159: make_length_attrs () ! 1160: { ! 1161: static char *new_names[] = {"*insn_default_length", ! 1162: "*insn_variable_length_p", ! 1163: "*insn_current_length"}; ! 1164: static rtx (*no_address_fn[]) () = {identity_fn, zero_fn, zero_fn}; ! 1165: static rtx (*address_fn[]) () = {max_fn, one_fn, identity_fn}; ! 1166: int i; ! 1167: struct attr_desc *length_attr, *new_attr; ! 1168: struct attr_value *av, *new_av; ! 1169: struct insn_ent *ie, *new_ie; ! 1170: ! 1171: /* See if length attribute is defined. If so, it must be numeric. Make ! 1172: it special so we don't output anything for it. */ ! 1173: length_attr = find_attr ("length", 0); ! 1174: if (length_attr == 0) ! 1175: return; ! 1176: ! 1177: if (! length_attr->is_numeric) ! 1178: fatal ("length attribute must be numeric."); ! 1179: ! 1180: length_attr->is_special = 1; ! 1181: ! 1182: /* Make each new attribute, in turn. */ ! 1183: for (i = 0; i < sizeof new_names / sizeof new_names[0]; i++) ! 1184: { ! 1185: make_internal_attr (new_names[i], ! 1186: substitute_address (length_attr->default_val->value, ! 1187: no_address_fn[i], address_fn[i]), ! 1188: 0); ! 1189: new_attr = find_attr (new_names[i], 0); ! 1190: for (av = length_attr->first_value; av; av = av->next) ! 1191: for (ie = av->first_insn; ie; ie = ie->next) ! 1192: { ! 1193: new_av = get_attr_value (substitute_address (av->value, ! 1194: no_address_fn[i], ! 1195: address_fn[i]), ! 1196: new_attr, ie->insn_code); ! 1197: new_ie = (struct insn_ent *) xmalloc (sizeof (struct insn_ent)); ! 1198: new_ie->insn_code = ie->insn_code; ! 1199: new_ie->insn_index = ie->insn_index; ! 1200: insert_insn_ent (new_av, new_ie); ! 1201: } ! 1202: } ! 1203: } ! 1204: ! 1205: /* Utility functions called from above routine. */ ! 1206: ! 1207: static rtx ! 1208: identity_fn (exp) ! 1209: rtx exp; ! 1210: { ! 1211: return exp; ! 1212: } ! 1213: ! 1214: static rtx ! 1215: zero_fn (exp) ! 1216: rtx exp; ! 1217: { ! 1218: return make_numeric_value (0); ! 1219: } ! 1220: ! 1221: static rtx ! 1222: one_fn (exp) ! 1223: rtx exp; ! 1224: { ! 1225: return make_numeric_value (1); ! 1226: } ! 1227: ! 1228: static rtx ! 1229: max_fn (exp) ! 1230: rtx exp; ! 1231: { ! 1232: return make_numeric_value (max_attr_value (exp)); ! 1233: } ! 1234: ! 1235: /* Take a COND expression and see if any of the conditions in it can be ! 1236: simplified. If any are known true or known false for the particular insn ! 1237: code, the COND can be further simplified. ! 1238: ! 1239: Also call ourselves on any COND operations that are values of this COND. ! 1240: ! 1241: We only do the first replacement found directly and call ourselves ! 1242: recursively for subsequent replacements. */ ! 1243: ! 1244: static rtx ! 1245: simplify_cond (exp, insn_code, insn_index) ! 1246: rtx exp; ! 1247: int insn_code, insn_index; ! 1248: { ! 1249: int i, j; ! 1250: rtx newtest; ! 1251: rtx value; ! 1252: rtx newexp = exp; ! 1253: ! 1254: for (i = 0; i < XVECLEN (exp, 0); i += 2) ! 1255: { ! 1256: newtest = SIMPLIFY_TEST_EXP (XVECEXP (exp, 0, i), insn_code, insn_index); ! 1257: if (newtest == true_rtx) ! 1258: { ! 1259: /* Make a new COND with any previous conditions and the value for ! 1260: this pair as the default value. */ ! 1261: newexp = rtx_alloc (COND); ! 1262: XVEC (newexp, 0) = rtvec_alloc (i); ! 1263: for (j = 0; j < i; j++) ! 1264: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1265: ! 1266: XEXP (newexp, 1) = XVECEXP (exp, 0, i + 1); ! 1267: break; ! 1268: } ! 1269: ! 1270: else if (newtest == false_rtx) ! 1271: { ! 1272: /* Build a new COND without this test. */ ! 1273: newexp = rtx_alloc (COND); ! 1274: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2); ! 1275: for (j = 0; j < i; j++) ! 1276: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1277: ! 1278: for (j = i; j < XVECLEN (newexp, 0); j++) ! 1279: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2); ! 1280: ! 1281: XEXP (newexp, 1) = XEXP (exp, 1); ! 1282: break; ! 1283: } ! 1284: ! 1285: else if (newtest != XVECEXP (exp, 0, i)) ! 1286: { ! 1287: newexp = rtx_alloc (COND); ! 1288: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0)); ! 1289: for (j = 0; j < XVECLEN (exp, 0); j++) ! 1290: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1291: XEXP (newexp, 1) = XEXP (exp, 1); ! 1292: ! 1293: XVECEXP (newexp, 0, i) = newtest; ! 1294: break; ! 1295: } ! 1296: ! 1297: /* See if this value may need simplification. */ ! 1298: if (GET_CODE (XVECEXP (exp, 0, i + 1)) == COND) ! 1299: { ! 1300: value = simplify_cond (XVECEXP (exp, 0, i + 1), ! 1301: insn_code, insn_index); ! 1302: if (value != XVECEXP (exp, 0, i + 1)) ! 1303: { ! 1304: newexp = rtx_alloc (COND); ! 1305: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0)); ! 1306: for (j = 0; j < XVECLEN (exp, 0); j++) ! 1307: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1308: XEXP (newexp, 1) = XEXP (exp, 1); ! 1309: ! 1310: XVECEXP (newexp, 0, i + 1) = value; ! 1311: break; ! 1312: } ! 1313: } ! 1314: ! 1315: /* If this is the last condition in a COND and our value is the same ! 1316: as the default value, our test isn't needed. */ ! 1317: if (i == XVECLEN (exp, 0) - 2 ! 1318: && rtx_equal_p (XVECEXP (exp, 0, i + 1), XEXP (exp, 1))) ! 1319: { ! 1320: newexp = rtx_alloc (COND); ! 1321: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2); ! 1322: for (j = 0; j < i; j++) ! 1323: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1324: XEXP (newexp, 1) = XEXP (exp, 1); ! 1325: break; ! 1326: } ! 1327: ! 1328: /* If this value and the value for the next test are the same, merge the ! 1329: tests. */ ! 1330: else if (i != XVECLEN (exp, 0) - 2 ! 1331: && rtx_equal_p (XVECEXP (exp, 0, i + 1), ! 1332: XVECEXP (exp, 0, i + 3))) ! 1333: { ! 1334: newexp = rtx_alloc (COND); ! 1335: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0) - 2); ! 1336: for (j = 0; j < i; j++) ! 1337: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1338: ! 1339: XVECEXP (newexp, 0, j) ! 1340: = insert_right_side (IOR, XVECEXP (exp, 0, i), ! 1341: XVECEXP (exp, 0, i + 2), ! 1342: insn_code, insn_index); ! 1343: XVECEXP (newexp, 0, j + 1) = XVECEXP (exp, 0, i + 1); ! 1344: ! 1345: for (j = i + 2; j < XVECLEN (newexp, 0); j++) ! 1346: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j + 2); ! 1347: ! 1348: XEXP (newexp, 1) = XEXP (exp, 1); ! 1349: break; ! 1350: } ! 1351: } ! 1352: ! 1353: /* See if default value needs simplification. */ ! 1354: if (GET_CODE (XEXP (exp, 1)) == COND) ! 1355: { ! 1356: value = simplify_cond (XEXP (exp, 1), insn_code, insn_index); ! 1357: if (value != XEXP (exp, 1)) ! 1358: { ! 1359: newexp = rtx_alloc (COND); ! 1360: XVEC (newexp, 0) = rtvec_alloc (XVECLEN (exp, 0)); ! 1361: for (j = 0; j < XVECLEN (exp, 0); j++) ! 1362: XVECEXP (newexp, 0, j) = XVECEXP (exp, 0, j); ! 1363: XEXP (newexp, 1) = value; ! 1364: } ! 1365: } ! 1366: ! 1367: if (exp == newexp) ! 1368: return exp; ! 1369: else if (XVECLEN (newexp, 0) == 1) ! 1370: return XVECEXP (newexp, 0, 0); ! 1371: else ! 1372: return simplify_cond (newexp, insn_code, insn_index); ! 1373: } ! 1374: ! 1375: /* Remove an insn entry from an attribute value. */ ! 1376: ! 1377: static void ! 1378: remove_insn_ent (av, ie) ! 1379: struct attr_value *av; ! 1380: struct insn_ent *ie; ! 1381: { ! 1382: struct insn_ent *previe; ! 1383: ! 1384: if (av->first_insn == ie) ! 1385: av->first_insn = ie->next; ! 1386: else ! 1387: { ! 1388: for (previe = av->first_insn; previe->next != ie; previe = previe->next) ! 1389: ; ! 1390: previe->next = ie->next; ! 1391: } ! 1392: ! 1393: av->num_insns--; ! 1394: if (ie->insn_code == -1) ! 1395: av->has_asm_insn = 0; ! 1396: } ! 1397: ! 1398: /* Insert an insn entry in an attribute value list. */ ! 1399: ! 1400: static void ! 1401: insert_insn_ent (av, ie) ! 1402: struct attr_value *av; ! 1403: struct insn_ent *ie; ! 1404: { ! 1405: ie->next = av->first_insn; ! 1406: av->first_insn = ie; ! 1407: av->num_insns++; ! 1408: if (ie->insn_code == -1) ! 1409: av->has_asm_insn = 1; ! 1410: } ! 1411: ! 1412: /* This is a utility routine to take an expression that is a tree of either ! 1413: AND or IOR expressions and insert a new term. The new term will be ! 1414: inserted at the right side of the first node whose code does not match ! 1415: the root. A new node will be created with the root's code. Its left ! 1416: side will be the old right side and its right side will be the new ! 1417: term. ! 1418: ! 1419: If the `term' is itself a tree, all its leaves will be inserted. */ ! 1420: ! 1421: static rtx ! 1422: insert_right_side (code, exp, term, insn_code, insn_index) ! 1423: RTX_CODE code; ! 1424: rtx exp; ! 1425: rtx term; ! 1426: int insn_code, insn_index; ! 1427: { ! 1428: rtx newexp; ! 1429: ! 1430: if (GET_CODE (term) == code) ! 1431: { ! 1432: exp = insert_right_side (code, exp, XEXP (term, 0), ! 1433: insn_code, insn_index); ! 1434: exp = insert_right_side (code, exp, XEXP (term, 1), ! 1435: insn_code, insn_index); ! 1436: ! 1437: return exp; ! 1438: } ! 1439: ! 1440: if (GET_CODE (exp) == code) ! 1441: { ! 1442: /* Make a copy of this expression and call recursively. */ ! 1443: newexp = rtx_alloc (code); ! 1444: XEXP (newexp, 0) = XEXP (exp, 0); ! 1445: XEXP (newexp, 1) = insert_right_side (code, XEXP (exp, 1), ! 1446: term, insn_code, insn_index); ! 1447: } ! 1448: else ! 1449: { ! 1450: /* Insert the new term. */ ! 1451: newexp = rtx_alloc (code); ! 1452: XEXP (newexp, 0) = exp; ! 1453: XEXP (newexp, 1) = term; ! 1454: } ! 1455: ! 1456: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1457: } ! 1458: ! 1459: /* If we have an expression which AND's a bunch of ! 1460: (not (eq_attrq "alternative" "n")) ! 1461: terms, we may have covered all or all but one of the possible alternatives. ! 1462: If so, we can optimize. Similarly for IOR's of EQ_ATTR. ! 1463: ! 1464: This routine is passed an expression and either AND or IOR. It returns a ! 1465: bitmask indicating which alternatives are present. */ ! 1466: ! 1467: static int ! 1468: compute_alternative_mask (exp, code) ! 1469: rtx exp; ! 1470: RTX_CODE code; ! 1471: { ! 1472: if (GET_CODE (exp) == code) ! 1473: return compute_alternative_mask (XEXP (exp, 0), code) ! 1474: | compute_alternative_mask (XEXP (exp, 1), code); ! 1475: ! 1476: else if (code == AND && GET_CODE (exp) == NOT ! 1477: && GET_CODE (XEXP (exp, 0)) == EQ_ATTR ! 1478: && XSTR (XEXP (exp, 0), 0) == alternative_name) ! 1479: return 1 << atoi (XSTR (XEXP (exp, 0), 1)); ! 1480: ! 1481: else if (code == IOR && GET_CODE (exp) == EQ_ATTR ! 1482: && XSTR (exp, 0) == alternative_name) ! 1483: return 1 << atoi (XSTR (exp, 1)); ! 1484: ! 1485: else ! 1486: return 0; ! 1487: } ! 1488: ! 1489: /* Given I, a single-bit mask, return RTX to compare the `alternative' ! 1490: attribute with the value represented by that bit. */ ! 1491: ! 1492: static rtx ! 1493: make_alternative_compare (mask) ! 1494: int mask; ! 1495: { ! 1496: rtx newexp; ! 1497: int i; ! 1498: char *alternative; ! 1499: ! 1500: /* Find the bit. */ ! 1501: for (i = 0; (mask & (1 << i)) == 0; i++) ! 1502: ; ! 1503: ! 1504: alternative = (char *) xmalloc (3); ! 1505: sprintf (alternative, "%d", i); ! 1506: ! 1507: newexp = rtx_alloc (EQ_ATTR); ! 1508: XSTR (newexp, 0) = alternative_name; ! 1509: XSTR (newexp, 1) = alternative; ! 1510: RTX_UNCHANGING_P (newexp) = 1; ! 1511: ! 1512: return newexp; ! 1513: } ! 1514: ! 1515: /* If we are processing an (eq_attr "attr" "value") test, we find the value ! 1516: of "attr" for this insn code. From that value, we can compute a test ! 1517: showing when the EQ_ATTR will be true. This routine performs that ! 1518: computation. If a test condition involves an address, we leave the EQ_ATTR ! 1519: intact because addresses are only valid for the `length' attribute. */ ! 1520: ! 1521: static rtx ! 1522: evaluate_eq_attr (exp, value, insn_code, insn_index) ! 1523: rtx exp; ! 1524: rtx value; ! 1525: int insn_code, insn_index; ! 1526: { ! 1527: rtx orexp, andexp; ! 1528: rtx right; ! 1529: rtx newexp; ! 1530: int i; ! 1531: ! 1532: if (GET_CODE (value) == CONST_STRING) ! 1533: { ! 1534: if (! strcmp (XSTR (value, 0), XSTR (exp, 1))) ! 1535: newexp = true_rtx; ! 1536: else ! 1537: newexp = false_rtx; ! 1538: } ! 1539: else if (GET_CODE (value) == COND) ! 1540: { ! 1541: /* We construct an IOR of all the cases for which the requested attribute ! 1542: value is present. Since we start with FALSE, if it is not present, ! 1543: FALSE will be returned. ! 1544: ! 1545: Each case is the AND of the NOT's of the previous conditions with the ! 1546: current condition; in the default case the current condition is TRUE. ! 1547: ! 1548: For each possible COND value, call ourselves recursively. ! 1549: ! 1550: The extra TRUE and FALSE expressions will be eliminated by another ! 1551: call to the simplification routine. */ ! 1552: ! 1553: orexp = false_rtx; ! 1554: andexp = true_rtx; ! 1555: ! 1556: for (i = 0; i < XVECLEN (value, 0); i += 2) ! 1557: { ! 1558: right = insert_right_side (AND, andexp, ! 1559: XVECEXP (value, 0, i), ! 1560: insn_code, insn_index); ! 1561: right = insert_right_side (AND, right, ! 1562: evaluate_eq_attr (exp, XVECEXP (value, 0, i + 1), ! 1563: insn_code, insn_index), ! 1564: insn_code, insn_index); ! 1565: orexp = insert_right_side (IOR, orexp, right, ! 1566: insn_code, insn_index); ! 1567: ! 1568: /* Add this condition into the AND expression. */ ! 1569: newexp = rtx_alloc (NOT); ! 1570: XEXP (newexp, 0) = XVECEXP (value, 0, i); ! 1571: andexp = insert_right_side (AND, andexp, newexp, ! 1572: insn_code, insn_index); ! 1573: } ! 1574: ! 1575: /* Handle the default case. */ ! 1576: right = insert_right_side (AND, andexp, ! 1577: evaluate_eq_attr (exp, XEXP (value, 1), ! 1578: insn_code, insn_index), ! 1579: insn_code, insn_index); ! 1580: newexp = insert_right_side (IOR, orexp, right, insn_code, insn_index); ! 1581: } ! 1582: else ! 1583: abort (); ! 1584: ! 1585: /* If uses an address, must return original expression. */ ! 1586: ! 1587: address_used = 0; ! 1588: walk_attr_value (newexp); ! 1589: ! 1590: if (address_used) ! 1591: return exp; ! 1592: else ! 1593: return newexp; ! 1594: } ! 1595: ! 1596: /* This routine is called when an AND of a term with a tree of AND's is ! 1597: encountered. If the term or its complement is present in the tree, it ! 1598: can be replaced with TRUE or FALSE, respectively. ! 1599: ! 1600: Note that (eq_attr "att" "v1") and (eq_attr "att" "v2") cannot both ! 1601: be true and hence are complementary. ! 1602: ! 1603: There is one special case: If we see ! 1604: (and (not (eq_attr "att" "v1")) ! 1605: (eq_attr "att" "v2")) ! 1606: this can be replaced by (eq_attr "att" "v2"). To do this we need to ! 1607: replace the term, not anything in the AND tree. So we pass a pointer to ! 1608: the term. */ ! 1609: ! 1610: static rtx ! 1611: simplify_and_tree (exp, pterm, insn_code, insn_index) ! 1612: rtx exp; ! 1613: rtx *pterm; ! 1614: int insn_code, insn_index; ! 1615: { ! 1616: rtx left, right; ! 1617: rtx newexp; ! 1618: rtx temp; ! 1619: int left_eliminates_term, right_eliminates_term; ! 1620: ! 1621: if (GET_CODE (exp) == AND) ! 1622: { ! 1623: left = simplify_and_tree (XEXP (exp, 0), pterm, insn_code, insn_index); ! 1624: right = simplify_and_tree (XEXP (exp, 1), pterm, insn_code, insn_index); ! 1625: if (left != XEXP (exp, 0) || right != XEXP (exp, 1)) ! 1626: { ! 1627: newexp = rtx_alloc (GET_CODE (exp)); ! 1628: XEXP (newexp, 0) = left; ! 1629: XEXP (newexp, 1) = right; ! 1630: ! 1631: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1632: } ! 1633: } ! 1634: ! 1635: else if (GET_CODE (exp) == IOR) ! 1636: { ! 1637: /* For the IOR case, we do the same as above, except that we can ! 1638: only eliminate `term' if both sides of the IOR would do so. */ ! 1639: temp = *pterm; ! 1640: left = simplify_and_tree (XEXP (exp, 0), &temp, insn_code, insn_index); ! 1641: left_eliminates_term = (temp == true_rtx); ! 1642: ! 1643: temp = *pterm; ! 1644: right = simplify_and_tree (XEXP (exp, 1), &temp, insn_code, insn_index); ! 1645: right_eliminates_term = (temp == true_rtx); ! 1646: ! 1647: if (left_eliminates_term && right_eliminates_term) ! 1648: *pterm = true_rtx; ! 1649: ! 1650: if (left != XEXP (exp, 0) || right != XEXP (exp, 1)) ! 1651: { ! 1652: newexp = rtx_alloc (GET_CODE (exp)); ! 1653: XEXP (newexp, 0) = left; ! 1654: XEXP (newexp, 1) = right; ! 1655: ! 1656: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1657: } ! 1658: } ! 1659: ! 1660: /* Check for simplifications. Do some extra checking here since this ! 1661: routine is called so many times. */ ! 1662: ! 1663: if (exp == *pterm) ! 1664: return true_rtx; ! 1665: ! 1666: else if (GET_CODE (exp) == NOT && XEXP (exp, 0) == *pterm) ! 1667: return false_rtx; ! 1668: ! 1669: else if (GET_CODE (*pterm) == NOT && exp == XEXP (*pterm, 0)) ! 1670: return false_rtx; ! 1671: ! 1672: else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == EQ_ATTR) ! 1673: { ! 1674: if (XSTR (exp, 0) != XSTR (*pterm, 0)) ! 1675: return exp; ! 1676: ! 1677: if (! strcmp (XSTR (exp, 1), XSTR (*pterm, 1))) ! 1678: return true_rtx; ! 1679: else ! 1680: return false_rtx; ! 1681: } ! 1682: ! 1683: else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT ! 1684: && GET_CODE (XEXP (exp, 0)) == EQ_ATTR) ! 1685: { ! 1686: if (XSTR (*pterm, 0) != XSTR (XEXP (exp, 0), 0)) ! 1687: return exp; ! 1688: ! 1689: if (! strcmp (XSTR (*pterm, 1), XSTR (XEXP (exp, 0), 1))) ! 1690: return false_rtx; ! 1691: else ! 1692: return true_rtx; ! 1693: } ! 1694: ! 1695: else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT ! 1696: && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR) ! 1697: { ! 1698: if (XSTR (exp, 0) != XSTR (XEXP (*pterm, 0), 0)) ! 1699: return exp; ! 1700: ! 1701: if (! strcmp (XSTR (exp, 1), XSTR (XEXP (*pterm, 0), 1))) ! 1702: return false_rtx; ! 1703: else ! 1704: *pterm = true_rtx; ! 1705: } ! 1706: ! 1707: else if (GET_CODE (exp) == NOT && GET_CODE (*pterm) == NOT) ! 1708: { ! 1709: if (rtx_equal_p (XEXP (exp, 0), XEXP (*pterm, 0))) ! 1710: return true_rtx; ! 1711: } ! 1712: ! 1713: else if (GET_CODE (exp) == NOT) ! 1714: { ! 1715: if (rtx_equal_p (XEXP (exp, 0), *pterm)) ! 1716: return false_rtx; ! 1717: } ! 1718: ! 1719: else if (GET_CODE (*pterm) == NOT) ! 1720: { ! 1721: if (rtx_equal_p (XEXP (*pterm, 0), exp)) ! 1722: return false_rtx; ! 1723: } ! 1724: ! 1725: else if (rtx_equal_p (exp, *pterm)) ! 1726: return true_rtx; ! 1727: ! 1728: return exp; ! 1729: } ! 1730: ! 1731: /* Similiar to `simplify_and_tree', but for IOR trees. */ ! 1732: ! 1733: static rtx ! 1734: simplify_or_tree (exp, pterm, insn_code, insn_index) ! 1735: rtx exp; ! 1736: rtx *pterm; ! 1737: int insn_code, insn_index; ! 1738: { ! 1739: rtx left, right; ! 1740: rtx newexp; ! 1741: rtx temp; ! 1742: int left_eliminates_term, right_eliminates_term; ! 1743: ! 1744: if (GET_CODE (exp) == IOR) ! 1745: { ! 1746: left = simplify_or_tree (XEXP (exp, 0), pterm, insn_code, insn_index); ! 1747: right = simplify_or_tree (XEXP (exp, 1), pterm, insn_code, insn_index); ! 1748: if (left != XEXP (exp, 0) || right != XEXP (exp, 1)) ! 1749: { ! 1750: newexp = rtx_alloc (GET_CODE (exp)); ! 1751: XEXP (newexp, 0) = left; ! 1752: XEXP (newexp, 1) = right; ! 1753: ! 1754: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1755: } ! 1756: } ! 1757: ! 1758: else if (GET_CODE (exp) == AND) ! 1759: { ! 1760: /* For the AND case, we do the same as above, except that we can ! 1761: only eliminate `term' if both sides of the AND would do so. */ ! 1762: temp = *pterm; ! 1763: left = simplify_or_tree (XEXP (exp, 0), &temp, insn_code, insn_index); ! 1764: left_eliminates_term = (temp == false_rtx); ! 1765: ! 1766: temp = *pterm; ! 1767: right = simplify_or_tree (XEXP (exp, 1), &temp, insn_code, insn_index); ! 1768: right_eliminates_term = (temp == false_rtx); ! 1769: ! 1770: if (left_eliminates_term && right_eliminates_term) ! 1771: *pterm = false_rtx; ! 1772: ! 1773: if (left != XEXP (exp, 0) || right != XEXP (exp, 1)) ! 1774: { ! 1775: newexp = rtx_alloc (GET_CODE (exp)); ! 1776: XEXP (newexp, 0) = left; ! 1777: XEXP (newexp, 1) = right; ! 1778: ! 1779: exp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1780: } ! 1781: } ! 1782: ! 1783: if (rtx_equal_p (exp, *pterm)) ! 1784: return false_rtx; ! 1785: ! 1786: else if (GET_CODE (exp) == NOT && rtx_equal_p (XEXP (exp, 0), *pterm)) ! 1787: return true_rtx; ! 1788: ! 1789: else if (GET_CODE (*pterm) == NOT && rtx_equal_p (XEXP (*pterm, 0), exp)) ! 1790: return true_rtx; ! 1791: ! 1792: else if (GET_CODE (*pterm) == EQ_ATTR && GET_CODE (exp) == NOT ! 1793: && GET_CODE (XEXP (exp, 0)) == EQ_ATTR ! 1794: && XSTR (*pterm, 0) == XSTR (XEXP (exp, 0), 0)) ! 1795: *pterm = false_rtx; ! 1796: ! 1797: else if (GET_CODE (exp) == EQ_ATTR && GET_CODE (*pterm) == NOT ! 1798: && GET_CODE (XEXP (*pterm, 0)) == EQ_ATTR ! 1799: && XSTR (exp, 0) == XSTR (XEXP (*pterm, 0), 0)) ! 1800: return false_rtx; ! 1801: ! 1802: return exp; ! 1803: } ! 1804: ! 1805: /* Given an expression, see if it can be simplified for a particular insn ! 1806: code based on the values of other attributes being tested. This can ! 1807: eliminate nested get_attr_... calls. ! 1808: ! 1809: Note that if an endless recursion is specified in the patterns, the ! 1810: optimization will loop. However, it will do so in precisely the cases where ! 1811: an infinite recursion loop could occur during compilation. It's better that ! 1812: it occurs here! */ ! 1813: ! 1814: static rtx ! 1815: simplify_test_exp (exp, insn_code, insn_index) ! 1816: rtx exp; ! 1817: int insn_code, insn_index; ! 1818: { ! 1819: rtx left, right; ! 1820: struct attr_desc *attr; ! 1821: struct attr_value *av; ! 1822: struct insn_ent *ie; ! 1823: int i; ! 1824: rtx newexp = exp; ! 1825: ! 1826: switch (GET_CODE (exp)) ! 1827: { ! 1828: case AND: ! 1829: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index); ! 1830: right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index); ! 1831: ! 1832: /* If either side is an IOR and we have (eq_attr "alternative" ..") ! 1833: present on both sides, apply the distributive law since this will ! 1834: yield simplications. */ ! 1835: if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR) ! 1836: && compute_alternative_mask (left, IOR) ! 1837: && compute_alternative_mask (right, IOR)) ! 1838: { ! 1839: if (GET_CODE (left) == IOR) ! 1840: { ! 1841: rtx tem = left; ! 1842: left = right; ! 1843: right = tem; ! 1844: } ! 1845: ! 1846: newexp = rtx_alloc (IOR); ! 1847: XEXP (newexp, 0) = rtx_alloc (AND); ! 1848: XEXP (newexp, 1) = rtx_alloc (AND); ! 1849: XEXP (XEXP (newexp, 0), 0) = XEXP (XEXP (newexp, 1), 0) = left; ! 1850: XEXP (XEXP (newexp, 0), 1) = XEXP (right, 0); ! 1851: XEXP (XEXP (newexp, 1), 1) = XEXP (right, 1); ! 1852: ! 1853: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1854: } ! 1855: ! 1856: /* Try with the term on both sides. */ ! 1857: right = simplify_and_tree (right, &left, insn_code, insn_index); ! 1858: if (left == XEXP (exp, 0) && right == XEXP (exp, 1)) ! 1859: left = simplify_and_tree (left, &right, insn_code, insn_index); ! 1860: ! 1861: if (left == false_rtx || right == false_rtx) ! 1862: return false_rtx; ! 1863: else if (left == true_rtx) ! 1864: return right; ! 1865: else if (right == true_rtx) ! 1866: return left; ! 1867: ! 1868: /* See if all or all but one of the insn's alternatives are specified ! 1869: in this tree. Optimize if so. */ ! 1870: ! 1871: else if (insn_code >= 0 ! 1872: && (GET_CODE (left) == AND ! 1873: || (GET_CODE (left) == NOT ! 1874: && GET_CODE (XEXP (left, 0)) == EQ_ATTR ! 1875: && XSTR (XEXP (left, 0), 0) == alternative_name) ! 1876: || GET_CODE (right) == AND ! 1877: || (GET_CODE (right) == NOT ! 1878: && GET_CODE (XEXP (right, 0)) == EQ_ATTR ! 1879: && XSTR (XEXP (right, 0), 0) == alternative_name))) ! 1880: { ! 1881: i = compute_alternative_mask (exp, AND); ! 1882: if (i & ~insn_alternatives[insn_code]) ! 1883: fatal ("Illegal alternative specified for pattern number %d", ! 1884: insn_index); ! 1885: ! 1886: /* If all alternatives are excluded, this is false. */ ! 1887: i ^= insn_alternatives[insn_code]; ! 1888: if (i == 0) ! 1889: return false_rtx; ! 1890: else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1) ! 1891: { ! 1892: /* If just one excluded, AND a comparison with that one to the ! 1893: front of the tree. The others will be eliminated by ! 1894: optimization. We do not want to do this if the insn has one ! 1895: alternative and we have tested none of them! */ ! 1896: left = make_alternative_compare (i); ! 1897: right = simplify_and_tree (exp, &left, insn_code, insn_index); ! 1898: newexp = rtx_alloc (AND); ! 1899: XEXP (newexp, 0) = left; ! 1900: XEXP (newexp, 1) = right; ! 1901: ! 1902: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1903: } ! 1904: } ! 1905: ! 1906: if (left != XEXP (exp, 0) || right != XEXP (exp, 1)) ! 1907: { ! 1908: newexp = rtx_alloc (AND); ! 1909: XEXP (newexp, 0) = left; ! 1910: XEXP (newexp, 1) = right; ! 1911: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1912: } ! 1913: break; ! 1914: ! 1915: case IOR: ! 1916: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index); ! 1917: right = SIMPLIFY_TEST_EXP (XEXP (exp, 1), insn_code, insn_index); ! 1918: ! 1919: right = simplify_or_tree (right, &left, insn_code, insn_index); ! 1920: if (left == XEXP (exp, 0) && right == XEXP (exp, 1)) ! 1921: left = simplify_or_tree (left, &right, insn_code, insn_index); ! 1922: ! 1923: if (right == true_rtx || left == true_rtx) ! 1924: return true_rtx; ! 1925: else if (left == false_rtx) ! 1926: return right; ! 1927: else if (right == false_rtx) ! 1928: return left; ! 1929: ! 1930: /* Test for simple cases where the distributive law is useful. I.e., ! 1931: convert (ior (and (x) (y)) ! 1932: (and (x) (z))) ! 1933: to (and (x) ! 1934: (ior (y) (z))) ! 1935: */ ! 1936: ! 1937: else if (GET_CODE (left) == AND && GET_CODE (right) == AND ! 1938: && rtx_equal_p (XEXP (left, 0), XEXP (right, 0))) ! 1939: { ! 1940: newexp = rtx_alloc (IOR); ! 1941: XEXP (newexp, 0) = XEXP (left, 1); ! 1942: XEXP (newexp, 1) = XEXP (right, 1); ! 1943: ! 1944: left = XEXP (left, 0); ! 1945: right = newexp; ! 1946: newexp = rtx_alloc (AND); ! 1947: XEXP (newexp, 0) = left; ! 1948: XEXP (newexp, 1) = right; ! 1949: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1950: } ! 1951: ! 1952: /* See if all or all but one of the insn's alternatives are specified ! 1953: in this tree. Optimize if so. */ ! 1954: ! 1955: else if (insn_code >= 0 ! 1956: && (GET_CODE (left) == IOR ! 1957: || (GET_CODE (left) == EQ_ATTR ! 1958: && XSTR (left, 0) == alternative_name) ! 1959: || GET_CODE (right) == IOR ! 1960: || (GET_CODE (right) == EQ_ATTR ! 1961: && XSTR (right, 0) == alternative_name))) ! 1962: { ! 1963: i = compute_alternative_mask (exp, IOR); ! 1964: if (i & ~insn_alternatives[insn_code]) ! 1965: fatal ("Illegal alternative specified for pattern number %d", ! 1966: insn_index); ! 1967: ! 1968: /* If all alternatives are included, this is true. */ ! 1969: i ^= insn_alternatives[insn_code]; ! 1970: if (i == 0) ! 1971: return true_rtx; ! 1972: else if ((i & (i - 1)) == 0 && insn_alternatives[insn_code] > 1) ! 1973: { ! 1974: /* If just one excluded, IOR a comparison with that one to the ! 1975: front of the tree. The others will be eliminated by ! 1976: optimization. We do not want to do this if the insn has one ! 1977: alternative and we have tested none of them! */ ! 1978: left = make_alternative_compare (i); ! 1979: right = simplify_and_tree (exp, &left, insn_code, insn_index); ! 1980: newexp = rtx_alloc (IOR); ! 1981: XEXP (newexp, 0) = rtx_alloc (NOT); ! 1982: XEXP (XEXP (newexp, 0), 0) = left; ! 1983: XEXP (newexp, 1) = right; ! 1984: ! 1985: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1986: } ! 1987: } ! 1988: ! 1989: if (left != XEXP (exp, 0) || right != XEXP (exp, 1)) ! 1990: { ! 1991: newexp = rtx_alloc (IOR); ! 1992: XEXP (newexp, 0) = left; ! 1993: XEXP (newexp, 1) = right; ! 1994: return SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 1995: } ! 1996: break; ! 1997: ! 1998: case NOT: ! 1999: left = SIMPLIFY_TEST_EXP (XEXP (exp, 0), insn_code, insn_index); ! 2000: if (GET_CODE (left) == NOT) ! 2001: return XEXP (left, 0); ! 2002: ! 2003: if (left == false_rtx) ! 2004: return true_rtx; ! 2005: else if (left == true_rtx) ! 2006: return false_rtx; ! 2007: ! 2008: /* Try to apply De`Morgan's laws. */ ! 2009: else if (GET_CODE (left) == IOR) ! 2010: { ! 2011: newexp = rtx_alloc (AND); ! 2012: XEXP (newexp, 0) = rtx_alloc (NOT); ! 2013: XEXP (XEXP (newexp, 0), 0) = XEXP (left, 0); ! 2014: XEXP (newexp, 1) = rtx_alloc (NOT); ! 2015: XEXP (XEXP (newexp, 1), 0) = XEXP (left, 1); ! 2016: ! 2017: newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 2018: } ! 2019: else if (GET_CODE (left) == AND) ! 2020: { ! 2021: newexp = rtx_alloc (IOR); ! 2022: XEXP (newexp, 0) = rtx_alloc (NOT); ! 2023: XEXP (XEXP (newexp, 0), 0) = XEXP (left, 0); ! 2024: XEXP (newexp, 1) = rtx_alloc (NOT); ! 2025: XEXP (XEXP (newexp, 1), 0) = XEXP (left, 1); ! 2026: ! 2027: newexp = SIMPLIFY_TEST_EXP (newexp, insn_code, insn_index); ! 2028: } ! 2029: else if (left != XEXP (exp, 0)) ! 2030: { ! 2031: newexp = rtx_alloc (NOT); ! 2032: XEXP (newexp, 0) = left; ! 2033: } ! 2034: break; ! 2035: ! 2036: case EQ_ATTR: ! 2037: /* Look at the value for this insn code in the specified attribute. ! 2038: We normally can replace this comparison with the condition that ! 2039: would give this insn the values being tested for. */ ! 2040: if (XSTR (exp, 0) != alternative_name ! 2041: && (attr = find_attr (XSTR (exp, 0), 0)) != NULL) ! 2042: for (av = attr->first_value; av; av = av->next) ! 2043: for (ie = av->first_insn; ie; ie = ie->next) ! 2044: if (ie->insn_code == insn_code) ! 2045: return evaluate_eq_attr (exp, av->value, insn_code, insn_index); ! 2046: } ! 2047: ! 2048: /* We have already simplified this expression. Simplifying it again ! 2049: won't buy anything unless we weren't given a valid insn code ! 2050: to process (i.e., we are canonicalizing something.). */ ! 2051: if (insn_code != -2) ! 2052: RTX_UNCHANGING_P (newexp) = 1; ! 2053: ! 2054: return newexp; ! 2055: } ! 2056: ! 2057: /* Optimize the attribute lists by seeing if we can determine conditional ! 2058: values from the known values of other attributes. This will save subroutine ! 2059: calls during the compilation. */ ! 2060: ! 2061: static void ! 2062: optimize_attrs () ! 2063: { ! 2064: struct attr_desc *attr; ! 2065: struct attr_value *av; ! 2066: struct insn_ent *ie, *nextie; ! 2067: rtx newexp; ! 2068: int something_changed = 1; ! 2069: ! 2070: /* Loop until nothing changes for one iteration. */ ! 2071: while (something_changed) ! 2072: { ! 2073: something_changed = 0; ! 2074: for (attr = attrs; attr; attr = attr->next) ! 2075: for (av = attr->first_value; av; av = av->next) ! 2076: for (ie = av->first_insn; ie; ie = nextie) ! 2077: { ! 2078: nextie = ie->next; ! 2079: if (GET_CODE (av->value) != COND) ! 2080: continue; ! 2081: ! 2082: newexp = simplify_cond (av->value, ie->insn_code, ! 2083: ie->insn_index); ! 2084: if (newexp != av->value) ! 2085: { ! 2086: remove_insn_ent (av, ie); ! 2087: insert_insn_ent (get_attr_value (newexp, attr, ! 2088: ie->insn_code), ie); ! 2089: something_changed = 1; ! 2090: } ! 2091: } ! 2092: } ! 2093: } ! 2094: ! 2095: /* Create table entries for DEFINE_ATTR. */ ! 2096: ! 2097: static void ! 2098: gen_attr (exp) ! 2099: rtx exp; ! 2100: { ! 2101: struct attr_desc *attr; ! 2102: struct attr_value *av; ! 2103: char *name_ptr; ! 2104: char *p; ! 2105: ! 2106: /* Make a new attribute structure. Check for duplicate by looking at ! 2107: attr->default_val, since it is initialized by this routine. */ ! 2108: attr = find_attr (XSTR (exp, 0), 1); ! 2109: if (attr->default_val) ! 2110: fatal ("Duplicate definition for `%s' attribute", attr->name); ! 2111: ! 2112: if (*XSTR (exp, 1) == '\0') ! 2113: attr->is_numeric = 1; ! 2114: else ! 2115: { ! 2116: name_ptr = XSTR (exp, 1); ! 2117: while ((p = next_comma_elt (&name_ptr)) != NULL) ! 2118: { ! 2119: av = (struct attr_value *) xmalloc (sizeof (struct attr_value)); ! 2120: av->value = rtx_alloc (CONST_STRING); ! 2121: XSTR (av->value, 0) = p; ! 2122: av->next = attr->first_value; ! 2123: attr->first_value = av; ! 2124: av->first_insn = NULL; ! 2125: av->num_insns = 0; ! 2126: av->has_asm_insn = 0; ! 2127: } ! 2128: } ! 2129: ! 2130: if (! strcmp (attr->name, "length") && ! attr->is_numeric) ! 2131: fatal ("`length' attribute must take numeric values"); ! 2132: ! 2133: /* Set up the default value. */ ! 2134: check_attr_value (XEXP (exp, 2), attr); ! 2135: attr->default_val = get_attr_value (XEXP (exp, 2), attr, -2); ! 2136: } ! 2137: ! 2138: /* Given a pattern for DEFINE_PEEPHOLE or DEFINE_INSN, return the number of ! 2139: alternatives in the constraints. Assume all MATCH_OPERANDs have the same ! 2140: number of alternatives as this should be checked elsewhere. */ ! 2141: ! 2142: static int ! 2143: count_alternatives (exp) ! 2144: rtx exp; ! 2145: { ! 2146: int i, j, n; ! 2147: char *fmt; ! 2148: ! 2149: if (GET_CODE (exp) == MATCH_OPERAND) ! 2150: return n_comma_elts (XSTR (exp, 2)); ! 2151: ! 2152: for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp)); ! 2153: i < GET_RTX_LENGTH (GET_CODE (exp)); i++) ! 2154: switch (*fmt++) ! 2155: { ! 2156: case 'e': ! 2157: case 'u': ! 2158: n = count_alternatives (XEXP (exp, i)); ! 2159: if (n) ! 2160: return n; ! 2161: break; ! 2162: ! 2163: case 'E': ! 2164: case 'V': ! 2165: if (XVEC (exp, i) != NULL) ! 2166: for (j = 0; j < XVECLEN (exp, i); j++) ! 2167: { ! 2168: n = count_alternatives (XVECEXP (exp, i, j)); ! 2169: if (n) ! 2170: return n; ! 2171: } ! 2172: } ! 2173: ! 2174: return 0; ! 2175: } ! 2176: ! 2177: /* Returns non-zero if the given expression contains an EQ_ATTR with the ! 2178: `alternative' attribute. */ ! 2179: ! 2180: static int ! 2181: compares_alternatives_p (exp) ! 2182: rtx exp; ! 2183: { ! 2184: int i, j; ! 2185: char *fmt; ! 2186: ! 2187: if (GET_CODE (exp) == EQ_ATTR && XSTR (exp, 0) == alternative_name) ! 2188: return 1; ! 2189: ! 2190: for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp)); ! 2191: i < GET_RTX_LENGTH (GET_CODE (exp)); i++) ! 2192: switch (*fmt++) ! 2193: { ! 2194: case 'e': ! 2195: case 'u': ! 2196: if (compares_alternatives_p (XEXP (exp, i))) ! 2197: return 1; ! 2198: break; ! 2199: ! 2200: case 'E': ! 2201: for (j = 0; j < XVECLEN (exp, i); j++) ! 2202: if (compares_alternatives_p (XVECEXP (exp, i, j))) ! 2203: return 1; ! 2204: break; ! 2205: } ! 2206: ! 2207: return 0; ! 2208: } ! 2209: ! 2210: /* Returns non-zero is INNER is contained in EXP. */ ! 2211: ! 2212: static int ! 2213: contained_in_p (inner, exp) ! 2214: rtx inner; ! 2215: rtx exp; ! 2216: { ! 2217: int i, j; ! 2218: char *fmt; ! 2219: ! 2220: if (rtx_equal_p (inner, exp)) ! 2221: return 1; ! 2222: ! 2223: for (i = 0, fmt = GET_RTX_FORMAT (GET_CODE (exp)); ! 2224: i < GET_RTX_LENGTH (GET_CODE (exp)); i++) ! 2225: switch (*fmt++) ! 2226: { ! 2227: case 'e': ! 2228: case 'u': ! 2229: if (contained_in_p (inner, XEXP (exp, i))) ! 2230: return 1; ! 2231: break; ! 2232: ! 2233: case 'E': ! 2234: for (j = 0; j < XVECLEN (exp, i); j++) ! 2235: if (contained_in_p (inner, XVECEXP (exp, i, j))) ! 2236: return 1; ! 2237: break; ! 2238: } ! 2239: ! 2240: return 0; ! 2241: } ! 2242: ! 2243: /* Process DEFINE_PEEPHOLE, DEFINE_INSN, and DEFINE_ASM_ATTRIBUTES. */ ! 2244: ! 2245: static void ! 2246: gen_insn (exp) ! 2247: rtx exp; ! 2248: { ! 2249: struct insn_def *id; ! 2250: ! 2251: id = (struct insn_def *) xmalloc (sizeof (struct insn_def)); ! 2252: id->next = defs; ! 2253: defs = id; ! 2254: id->def = exp; ! 2255: ! 2256: switch (GET_CODE (exp)) ! 2257: { ! 2258: case DEFINE_INSN: ! 2259: id->insn_code = insn_code_number++; ! 2260: id->insn_index = insn_index_number++; ! 2261: id->num_alternatives = count_alternatives (exp); ! 2262: if (id->num_alternatives == 0) ! 2263: id->num_alternatives = 1; ! 2264: id->vec_idx = 4; ! 2265: break; ! 2266: ! 2267: case DEFINE_PEEPHOLE: ! 2268: id->insn_code = insn_code_number++; ! 2269: id->insn_index = insn_index_number++; ! 2270: id->num_alternatives = count_alternatives (exp); ! 2271: if (id->num_alternatives == 0) ! 2272: id->num_alternatives = 1; ! 2273: id->vec_idx = 3; ! 2274: break; ! 2275: ! 2276: case DEFINE_ASM_ATTRIBUTES: ! 2277: id->insn_code = -1; ! 2278: id->insn_index = -1; ! 2279: id->num_alternatives = 1; ! 2280: id->vec_idx = 0; ! 2281: got_define_asm_attributes = 1; ! 2282: break; ! 2283: } ! 2284: } ! 2285: ! 2286: /* Process a DEFINE_DELAY. Validate the vector length, check if annul ! 2287: true or annul false is specified, and make a `struct delay_desc'. */ ! 2288: ! 2289: static void ! 2290: gen_delay (def) ! 2291: rtx def; ! 2292: { ! 2293: struct delay_desc *delay; ! 2294: int i; ! 2295: ! 2296: if (XVECLEN (def, 1) % 3 != 0) ! 2297: fatal ("Number of elements in DEFINE_DELAY must be multiple of three."); ! 2298: ! 2299: for (i = 0; i < XVECLEN (def, 1); i += 3) ! 2300: { ! 2301: if (XVECEXP (def, 1, i + 1)) ! 2302: have_annul_true = 1; ! 2303: if (XVECEXP (def, 1, i + 2)) ! 2304: have_annul_false = 1; ! 2305: } ! 2306: ! 2307: delay = (struct delay_desc *) xmalloc (sizeof (struct delay_desc)); ! 2308: delay->def = def; ! 2309: delay->num = ++num_delays; ! 2310: delay->next = delays; ! 2311: delays = delay; ! 2312: } ! 2313: ! 2314: /* Process a DEFINE_FUNCTION_UNIT. ! 2315: ! 2316: This gives information about a function unit contained in the CPU. ! 2317: We fill in a `struct function_unit_op' and a `struct function_unit' ! 2318: with information used later by `expand_unit'. */ ! 2319: ! 2320: static void ! 2321: gen_unit (def) ! 2322: rtx def; ! 2323: { ! 2324: struct function_unit *unit; ! 2325: struct function_unit_op *op; ! 2326: ! 2327: /* See if we have already seen this function unit. If so, check that ! 2328: the multipicity and simultaneity values are the same. If not, make ! 2329: a structure for this function unit. */ ! 2330: for (unit = units; unit; unit = unit->next) ! 2331: if (! strcmp (unit->name, XSTR (def, 0))) ! 2332: { ! 2333: if (unit->multiplicity != XINT (def, 1) ! 2334: || unit->simultaneity != XINT (def, 2)) ! 2335: fatal ("Differing specifications given for `%s' function unit.", ! 2336: unit->name); ! 2337: break; ! 2338: } ! 2339: ! 2340: if (unit == 0) ! 2341: { ! 2342: unit = (struct function_unit *) xmalloc (sizeof (struct function_unit)); ! 2343: unit->name = XSTR (def, 0); ! 2344: unit->multiplicity = XINT (def, 1); ! 2345: unit->simultaneity = XINT (def, 2); ! 2346: unit->num = num_units++; ! 2347: unit->num_opclasses = 0; ! 2348: unit->condexp = false_rtx; ! 2349: unit->ops = 0; ! 2350: unit->next = units; ! 2351: units = unit; ! 2352: } ! 2353: ! 2354: /* Make a new operation class structure entry and initialize it. */ ! 2355: op = (struct function_unit_op *) xmalloc (sizeof (struct function_unit_op)); ! 2356: op->condexp = XEXP (def, 3); ! 2357: op->num = unit->num_opclasses++; ! 2358: op->ready = XINT (def, 4); ! 2359: op->next = unit->ops; ! 2360: unit->ops = op; ! 2361: ! 2362: /* Set our busy expression based on whether or not an optional conflict ! 2363: vector was specified. */ ! 2364: if (XVEC (def, 6)) ! 2365: { ! 2366: /* Compute the IOR of all the specified expressions. */ ! 2367: rtx orexp = false_rtx; ! 2368: int i; ! 2369: ! 2370: for (i = 0; i < XVECLEN (def, 6); i++) ! 2371: orexp = insert_right_side (IOR, orexp, XVECEXP (def, 6, i), -2); ! 2372: ! 2373: op->busyexp = rtx_alloc (IF_THEN_ELSE); ! 2374: XEXP (op->busyexp, 0) = orexp; ! 2375: XEXP (op->busyexp, 1) = make_numeric_value (XINT (def, 5)); ! 2376: XEXP (op->busyexp, 2) = make_numeric_value (0); ! 2377: } ! 2378: else ! 2379: op->busyexp = make_numeric_value (XINT (def, 5)); ! 2380: ! 2381: /* Merge our conditional into that of the function unit so we can determine ! 2382: which insns are used by the function unit. */ ! 2383: unit->condexp = insert_right_side (IOR, unit->condexp, op->condexp, -2); ! 2384: } ! 2385: ! 2386: /* Given a piece of RTX, print a C expression to test it's truth value. ! 2387: We use AND and IOR both for logical and bit-wise operations, so ! 2388: interpret them as logical unless they are inside a comparison expression. ! 2389: The second operand of this function will be non-zero in that case. */ ! 2390: ! 2391: static void ! 2392: write_test_expr (exp, in_comparison) ! 2393: rtx exp; ! 2394: int in_comparison; ! 2395: { ! 2396: int comparison_operator = 0; ! 2397: RTX_CODE code; ! 2398: struct attr_desc *attr; ! 2399: ! 2400: /* In order not to worry about operator precedence, surround our part of ! 2401: the expression with parentheses. */ ! 2402: ! 2403: printf ("("); ! 2404: code = GET_CODE (exp); ! 2405: switch (code) ! 2406: { ! 2407: /* Binary operators. */ ! 2408: case EQ: case NE: ! 2409: case GE: case GT: case GEU: case GTU: ! 2410: case LE: case LT: case LEU: case LTU: ! 2411: comparison_operator = 1; ! 2412: ! 2413: case PLUS: case MINUS: case MULT: case DIV: case MOD: ! 2414: case AND: case IOR: case XOR: ! 2415: case LSHIFT: case ASHIFT: case LSHIFTRT: case ASHIFTRT: ! 2416: write_test_expr (XEXP (exp, 0), in_comparison || comparison_operator); ! 2417: switch (code) ! 2418: { ! 2419: case EQ: ! 2420: printf (" == "); ! 2421: break; ! 2422: case NE: ! 2423: printf (" != "); ! 2424: break; ! 2425: case GE: ! 2426: printf (" >= "); ! 2427: break; ! 2428: case GT: ! 2429: printf (" > "); ! 2430: break; ! 2431: case GEU: ! 2432: printf (" >= (unsigned) "); ! 2433: break; ! 2434: case GTU: ! 2435: printf (" > (unsigned) "); ! 2436: break; ! 2437: case LE: ! 2438: printf (" <= "); ! 2439: break; ! 2440: case LT: ! 2441: printf (" < "); ! 2442: break; ! 2443: case LEU: ! 2444: printf (" <= (unsigned) "); ! 2445: break; ! 2446: case LTU: ! 2447: printf (" < (unsigned) "); ! 2448: break; ! 2449: case PLUS: ! 2450: printf (" + "); ! 2451: break; ! 2452: case MINUS: ! 2453: printf (" - "); ! 2454: break; ! 2455: case MULT: ! 2456: printf (" * "); ! 2457: break; ! 2458: case DIV: ! 2459: printf (" / "); ! 2460: break; ! 2461: case MOD: ! 2462: printf (" % "); ! 2463: break; ! 2464: case AND: ! 2465: if (in_comparison) ! 2466: printf (" & "); ! 2467: else ! 2468: printf (" && "); ! 2469: break; ! 2470: case IOR: ! 2471: if (in_comparison) ! 2472: printf (" | "); ! 2473: else ! 2474: printf (" || "); ! 2475: break; ! 2476: case XOR: ! 2477: printf (" ^ "); ! 2478: break; ! 2479: case LSHIFT: ! 2480: case ASHIFT: ! 2481: printf (" << "); ! 2482: break; ! 2483: case LSHIFTRT: ! 2484: case ASHIFTRT: ! 2485: printf (" >> "); ! 2486: break; ! 2487: } ! 2488: ! 2489: write_test_expr (XEXP (exp, 1), in_comparison || comparison_operator); ! 2490: break; ! 2491: ! 2492: case NOT: ! 2493: /* Special-case (not (eq_attrq "alternative" "x")) */ ! 2494: if (! in_comparison && GET_CODE (XEXP (exp, 0)) == EQ_ATTR ! 2495: && XSTR (XEXP (exp, 0), 0) == alternative_name) ! 2496: { ! 2497: printf ("which_alternative != %s", XSTR (XEXP (exp, 0), 1)); ! 2498: break; ! 2499: } ! 2500: ! 2501: /* Otherwise, fall through to normal unary operator. */ ! 2502: ! 2503: /* Unary operators. */ ! 2504: case ABS: case NEG: ! 2505: switch (code) ! 2506: { ! 2507: case NOT: ! 2508: if (in_comparison) ! 2509: printf ("~ "); ! 2510: else ! 2511: printf ("! "); ! 2512: break; ! 2513: case ABS: ! 2514: printf ("abs "); ! 2515: break; ! 2516: case NEG: ! 2517: printf ("-"); ! 2518: break; ! 2519: } ! 2520: ! 2521: write_test_expr (XEXP (exp, 0), in_comparison); ! 2522: break; ! 2523: ! 2524: /* Comparison test of an attribute with a value. Most of these will ! 2525: have been removed by optimization. Handle "alternative" ! 2526: specially and give error if EQ_ATTR present inside a comparison. */ ! 2527: case EQ_ATTR: ! 2528: if (in_comparison) ! 2529: fatal ("EQ_ATTR not valid inside comparison"); ! 2530: ! 2531: if (XSTR (exp, 0) == alternative_name) ! 2532: { ! 2533: printf ("which_alternative == %s", XSTR (exp, 1)); ! 2534: break; ! 2535: } ! 2536: ! 2537: attr = find_attr (XSTR (exp, 0), 0); ! 2538: if (! attr) abort (); ! 2539: printf ("get_attr_%s (insn) == ", attr->name); ! 2540: write_attr_valueq (attr, XSTR (exp, 1)); ! 2541: break; ! 2542: ! 2543: /* See if an operand matches a predicate. */ ! 2544: case MATCH_OPERAND: ! 2545: /* If only a mode is given, just ensure the mode matches the operand. ! 2546: If neither a mode nor predicate is given, error. */ ! 2547: if (XSTR (exp, 1) == NULL || *XSTR (exp, 1) == '\0') ! 2548: { ! 2549: if (GET_MODE (exp) == VOIDmode) ! 2550: fatal ("Null MATCH_OPERAND specified as test"); ! 2551: else ! 2552: printf ("GET_MODE (operands[%d]) == %smode", ! 2553: XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp))); ! 2554: } ! 2555: else ! 2556: printf ("%s (operands[%d], %smode)", ! 2557: XSTR (exp, 1), XINT (exp, 0), GET_MODE_NAME (GET_MODE (exp))); ! 2558: break; ! 2559: ! 2560: /* Constant integer. */ ! 2561: case CONST_INT: ! 2562: printf ("%d", XINT (exp, 0)); ! 2563: break; ! 2564: ! 2565: /* A random C expression. */ ! 2566: case SYMBOL_REF: ! 2567: printf ("%s", XSTR (exp, 0)); ! 2568: break; ! 2569: ! 2570: /* The address of the branch target. */ ! 2571: case MATCH_DUP: ! 2572: printf ("insn_addresses[INSN_UID (JUMP_LABEL (insn))]"); ! 2573: break; ! 2574: ! 2575: /* The address of the current insn. It would be more consistent with ! 2576: other usage to make this the address of the NEXT insn, but this gets ! 2577: too confusing because of the ambiguity regarding the length of the ! 2578: current insn. */ ! 2579: case PC: ! 2580: printf ("insn_current_address"); ! 2581: break; ! 2582: ! 2583: default: ! 2584: fatal ("bad RTX code `%s' in attribute calculation\n", ! 2585: GET_RTX_NAME (code)); ! 2586: } ! 2587: ! 2588: printf (")"); ! 2589: } ! 2590: ! 2591: /* Given an attribute value, return the maximum CONST_STRING argument ! 2592: encountered. It is assumed that they are all numeric. */ ! 2593: ! 2594: static int ! 2595: max_attr_value (exp) ! 2596: rtx exp; ! 2597: { ! 2598: int current_max = 0; ! 2599: int n; ! 2600: int i; ! 2601: ! 2602: if (GET_CODE (exp) == CONST_STRING) ! 2603: return atoi (XSTR (exp, 0)); ! 2604: ! 2605: else if (GET_CODE (exp) == COND) ! 2606: { ! 2607: for (i = 0; i < XVECLEN (exp, 0); i += 2) ! 2608: { ! 2609: n = max_attr_value (XVECEXP (exp, 0, i + 1)); ! 2610: if (n > current_max) ! 2611: current_max = n; ! 2612: } ! 2613: ! 2614: n = max_attr_value (XEXP (exp, 1)); ! 2615: if (n > current_max) ! 2616: current_max = n; ! 2617: } ! 2618: ! 2619: else ! 2620: abort (); ! 2621: ! 2622: return current_max; ! 2623: } ! 2624: ! 2625: /* Scan an attribute value, possibly a conditional, and record what actions ! 2626: will be required to do any conditional tests in it. ! 2627: ! 2628: Specifically, set ! 2629: `must_extract' if we need to extract the insn operands ! 2630: `must_constrain' if we must compute `which_alternative' ! 2631: `address_used' if an address expression was used ! 2632: */ ! 2633: ! 2634: static void ! 2635: walk_attr_value (exp) ! 2636: rtx exp; ! 2637: { ! 2638: register int i, j; ! 2639: register char *fmt; ! 2640: RTX_CODE code; ! 2641: ! 2642: if (exp == NULL) ! 2643: return; ! 2644: ! 2645: code = GET_CODE (exp); ! 2646: switch (code) ! 2647: { ! 2648: case SYMBOL_REF: ! 2649: /* Since this is an arbitrary expression, it can look at anything. */ ! 2650: must_extract = must_constrain = 1; ! 2651: return; ! 2652: ! 2653: case MATCH_OPERAND: ! 2654: must_extract = 1; ! 2655: return; ! 2656: ! 2657: case EQ_ATTR: ! 2658: if (XSTR (exp, 0) == alternative_name) ! 2659: must_extract = must_constrain = 1; ! 2660: return; ! 2661: ! 2662: case MATCH_DUP: ! 2663: case PC: ! 2664: address_used = 1; ! 2665: return; ! 2666: } ! 2667: ! 2668: for (i = 0, fmt = GET_RTX_FORMAT (code); i < GET_RTX_LENGTH (code); i++) ! 2669: switch (*fmt++) ! 2670: { ! 2671: case 'e': ! 2672: case 'u': ! 2673: walk_attr_value (XEXP (exp, i)); ! 2674: break; ! 2675: ! 2676: case 'E': ! 2677: if (XVEC (exp, i) != NULL) ! 2678: for (j = 0; j < XVECLEN (exp, i); j++) ! 2679: walk_attr_value (XVECEXP (exp, i, j)); ! 2680: break; ! 2681: } ! 2682: } ! 2683: ! 2684: /* Write out a function to obtain the attribute for a given INSN. */ ! 2685: ! 2686: static void ! 2687: write_attr_get (attr) ! 2688: struct attr_desc *attr; ! 2689: { ! 2690: struct attr_value *av, *common_av; ! 2691: ! 2692: /* Find the most used attribute value. Handle that as the `default' of the ! 2693: switch we will generate. */ ! 2694: common_av = find_most_used (attr); ! 2695: ! 2696: /* Write out start of function, then all values with explicit `case' lines, ! 2697: then a `default', then the value with the most uses. */ ! 2698: if (attr->is_numeric) ! 2699: printf ("int\n"); ! 2700: else ! 2701: printf ("enum attr_%s\n", attr->name); ! 2702: ! 2703: /* If the attribute name starts with a star, the remainder is the name of ! 2704: the subroutine to use, instead of `get_attr_...'. */ ! 2705: if (attr->name[0] == '*') ! 2706: printf ("%s (insn)\n", &attr->name[1]); ! 2707: else ! 2708: printf ("get_attr_%s (insn)\n", attr->name); ! 2709: printf (" rtx insn;\n"); ! 2710: printf ("{\n"); ! 2711: printf (" switch (recog_memoized (insn))\n"); ! 2712: printf (" {\n"); ! 2713: ! 2714: for (av = attr->first_value; av; av = av->next) ! 2715: if (av != common_av) ! 2716: write_attr_case (attr, av, 1, "return", ";", 4, true_rtx); ! 2717: ! 2718: write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); ! 2719: printf (" }\n}\n\n"); ! 2720: } ! 2721: ! 2722: /* Given an AND tree of known true terms (because we are inside an `if' with ! 2723: that as the condition or are in an `else' clause) and an expression, ! 2724: replace any known true terms with TRUE. Use `simplify_and_tree' to do ! 2725: the bulk of the work. */ ! 2726: ! 2727: static rtx ! 2728: eliminate_known_true (known_true, exp, insn_code, insn_index) ! 2729: rtx known_true; ! 2730: rtx exp; ! 2731: int insn_code, insn_index; ! 2732: { ! 2733: rtx term; ! 2734: ! 2735: known_true = SIMPLIFY_TEST_EXP (known_true, insn_code, insn_index); ! 2736: ! 2737: if (GET_CODE (known_true) == AND) ! 2738: { ! 2739: exp = eliminate_known_true (XEXP (known_true, 0), exp, ! 2740: insn_code, insn_index); ! 2741: exp = eliminate_known_true (XEXP (known_true, 1), exp, ! 2742: insn_code, insn_index); ! 2743: } ! 2744: else ! 2745: { ! 2746: term = known_true; ! 2747: exp = simplify_and_tree (exp, &term, insn_code, insn_index); ! 2748: } ! 2749: ! 2750: return exp; ! 2751: } ! 2752: ! 2753: /* Write out a series of tests and assignment statements to perform tests and ! 2754: sets of an attribute value. We are passed an indentation amount and prefix ! 2755: and suffix strings to write around each attribute value (e.g., "return" ! 2756: and ";"). */ ! 2757: ! 2758: static void ! 2759: write_attr_set (attr, indent, value, prefix, suffix, known_true, ! 2760: insn_code, insn_index) ! 2761: struct attr_desc *attr; ! 2762: int indent; ! 2763: rtx value; ! 2764: char *prefix; ! 2765: char *suffix; ! 2766: rtx known_true; ! 2767: int insn_code, insn_index; ! 2768: { ! 2769: if (GET_CODE (value) == CONST_STRING) ! 2770: { ! 2771: write_indent (indent); ! 2772: printf ("%s ", prefix); ! 2773: write_attr_value (attr, value); ! 2774: printf ("%s\n", suffix); ! 2775: } ! 2776: else if (GET_CODE (value) == COND) ! 2777: { ! 2778: /* Assume the default value will be the default of the COND unless we ! 2779: find an always true expression. */ ! 2780: rtx default_val = XEXP (value, 1); ! 2781: rtx our_known_true = known_true; ! 2782: rtx newexp; ! 2783: int first_if = 1; ! 2784: int i; ! 2785: ! 2786: for (i = 0; i < XVECLEN (value, 0); i += 2) ! 2787: { ! 2788: rtx testexp; ! 2789: rtx inner_true; ! 2790: ! 2791: testexp = eliminate_known_true (our_known_true, ! 2792: XVECEXP (value, 0, i), ! 2793: insn_code, insn_index); ! 2794: newexp = rtx_alloc (NOT); ! 2795: XEXP (newexp, 0) = testexp; ! 2796: newexp = insert_right_side (AND, our_known_true, newexp, ! 2797: insn_code, insn_index); ! 2798: ! 2799: /* If the test expression is always true or if the next `known_true' ! 2800: expression is always false, this is the last case, so break ! 2801: out and let this value be the `else' case. */ ! 2802: if (testexp == true_rtx || newexp == false_rtx) ! 2803: { ! 2804: default_val = XVECEXP (value, 0, i + 1); ! 2805: break; ! 2806: } ! 2807: ! 2808: /* Compute the expression to pass to our recursive call as being ! 2809: known true. */ ! 2810: inner_true = insert_right_side (AND, our_known_true, ! 2811: testexp, insn_code, insn_index); ! 2812: ! 2813: /* If this is always false, skip it. */ ! 2814: if (inner_true == false_rtx) ! 2815: continue; ! 2816: ! 2817: write_indent (indent); ! 2818: printf ("%sif ", first_if ? "" : "else "); ! 2819: first_if = 0; ! 2820: write_test_expr (testexp, 0); ! 2821: printf ("\n"); ! 2822: write_indent (indent + 2); ! 2823: printf ("{\n"); ! 2824: ! 2825: write_attr_set (attr, indent + 4, ! 2826: XVECEXP (value, 0, i + 1), prefix, suffix, ! 2827: inner_true, insn_code, insn_index); ! 2828: write_indent (indent + 2); ! 2829: printf ("}\n"); ! 2830: our_known_true = newexp; ! 2831: } ! 2832: ! 2833: if (! first_if) ! 2834: { ! 2835: write_indent (indent); ! 2836: printf ("else\n"); ! 2837: write_indent (indent + 2); ! 2838: printf ("{\n"); ! 2839: } ! 2840: ! 2841: write_attr_set (attr, first_if ? indent : indent + 4, default_val, ! 2842: prefix, suffix, our_known_true, insn_code, insn_index); ! 2843: ! 2844: if (! first_if) ! 2845: { ! 2846: write_indent (indent + 2); ! 2847: printf ("}\n"); ! 2848: } ! 2849: } ! 2850: else ! 2851: abort (); ! 2852: } ! 2853: ! 2854: /* Write out the computation for one attribute value. */ ! 2855: ! 2856: static void ! 2857: write_attr_case (attr, av, write_case_lines, prefix, suffix, indent, known_true) ! 2858: struct attr_desc *attr; ! 2859: struct attr_value *av; ! 2860: int write_case_lines; ! 2861: char *prefix, *suffix; ! 2862: int indent; ! 2863: rtx known_true; ! 2864: { ! 2865: struct insn_ent *ie; ! 2866: ! 2867: if (av->num_insns == 0) ! 2868: return; ! 2869: ! 2870: if (av->has_asm_insn) ! 2871: { ! 2872: write_indent (indent); ! 2873: printf ("case -1:\n"); ! 2874: write_indent (indent + 2); ! 2875: printf ("if (GET_CODE (PATTERN (insn)) != ASM_INPUT\n"); ! 2876: write_indent (indent + 2); ! 2877: printf (" && asm_noperands (PATTERN (insn)) < 0)\n"); ! 2878: write_indent (indent + 2); ! 2879: printf (" fatal_insn_not_found (insn);\n"); ! 2880: } ! 2881: ! 2882: if (write_case_lines) ! 2883: { ! 2884: for (ie = av->first_insn; ie; ie = ie->next) ! 2885: if (ie->insn_code != -1) ! 2886: { ! 2887: write_indent (indent); ! 2888: printf ("case %d:\n", ie->insn_code); ! 2889: } ! 2890: } ! 2891: else ! 2892: { ! 2893: write_indent (indent); ! 2894: printf ("default:\n"); ! 2895: } ! 2896: ! 2897: /* See what we have to do to handle output this value. */ ! 2898: must_extract = must_constrain = address_used = 0; ! 2899: walk_attr_value (av->value); ! 2900: ! 2901: if (must_extract) ! 2902: { ! 2903: write_indent (indent + 2); ! 2904: printf ("insn_extract (insn);\n"); ! 2905: } ! 2906: ! 2907: if (must_constrain) ! 2908: { ! 2909: #ifdef REGISTER_CONSTRAINTS ! 2910: write_indent (indent + 2); ! 2911: printf ("if (! constrain_operands (INSN_CODE (insn), reload_completed))\n"); ! 2912: write_indent (indent + 2); ! 2913: printf (" fatal_insn_not_found (insn);\n"); ! 2914: #endif ! 2915: } ! 2916: ! 2917: write_attr_set (attr, indent + 2, av->value, prefix, suffix, ! 2918: known_true, av->first_insn->insn_code, ! 2919: av->first_insn->insn_index); ! 2920: ! 2921: if (strncmp (prefix, "return", 6)) ! 2922: { ! 2923: write_indent (indent + 2); ! 2924: printf ("break;\n"); ! 2925: } ! 2926: printf ("\n"); ! 2927: } ! 2928: ! 2929: /* Utilities to write names in various forms. */ ! 2930: ! 2931: static void ! 2932: write_attr_valueq (attr, s) ! 2933: struct attr_desc *attr; ! 2934: char *s; ! 2935: { ! 2936: if (attr->is_numeric) ! 2937: printf ("%s", s); ! 2938: else ! 2939: { ! 2940: write_upcase (attr->name); ! 2941: printf ("_"); ! 2942: write_upcase (s); ! 2943: } ! 2944: } ! 2945: ! 2946: static void ! 2947: write_attr_value (attr, value) ! 2948: struct attr_desc *attr; ! 2949: rtx value; ! 2950: { ! 2951: if (GET_CODE (value) != CONST_STRING) ! 2952: abort (); ! 2953: ! 2954: write_attr_valueq (attr, XSTR (value, 0)); ! 2955: } ! 2956: ! 2957: static void ! 2958: write_upcase (str) ! 2959: char *str; ! 2960: { ! 2961: while (*str) ! 2962: if (*str < 'a' || *str > 'z') ! 2963: printf ("%c", *str++); ! 2964: else ! 2965: printf ("%c", *str++ - 'a' + 'A'); ! 2966: } ! 2967: ! 2968: static void ! 2969: write_indent (indent) ! 2970: int indent; ! 2971: { ! 2972: for (; indent > 8; indent -= 8) ! 2973: printf ("\t"); ! 2974: ! 2975: for (; indent; indent--) ! 2976: printf (" "); ! 2977: } ! 2978: ! 2979: /* Write a subroutine that is given an insn that requires a delay slot, a ! 2980: delay slot ordinal, and a candidate insn. It returns non-zero if the ! 2981: candidate can be placed in the specified delay slot of the insn. ! 2982: ! 2983: We can write as many as three subroutines. `eligible_for_delay' ! 2984: handles normal delay slots, `eligible_for_annul_true' indicates that ! 2985: the specified insn can be annulled if the branch is true, and likewise ! 2986: for `eligible_for_annul_false'. ! 2987: ! 2988: KIND is a string distingushing these three cases ("delay", "annul_true", ! 2989: or "annul_false"). */ ! 2990: ! 2991: static void ! 2992: write_eligible_delay (kind) ! 2993: char *kind; ! 2994: { ! 2995: struct delay_desc *delay; ! 2996: int max_slots; ! 2997: char str[50]; ! 2998: struct attr_desc *attr; ! 2999: struct attr_value *av, *common_av; ! 3000: int i; ! 3001: ! 3002: /* Compute the maximum number of delay slots required. We use the delay ! 3003: ordinal times this number plus one, plus the slot number as an index into ! 3004: the appropriate predicate to test. */ ! 3005: ! 3006: for (delay = delays, max_slots = 0; delay; delay = delay->next) ! 3007: if (XVECLEN (delay->def, 1) / 3 > max_slots) ! 3008: max_slots = XVECLEN (delay->def, 1) / 3; ! 3009: ! 3010: /* Write function prelude. */ ! 3011: ! 3012: printf ("int\n"); ! 3013: printf ("eligible_for_%s (delay_insn, slot, candidate_insn)\n", kind); ! 3014: printf (" rtx delay_insn;\n"); ! 3015: printf (" int slot;\n"); ! 3016: printf (" rtx candidate_insn;\n"); ! 3017: printf ("{\n"); ! 3018: printf (" rtx insn;\n"); ! 3019: printf ("\n"); ! 3020: printf (" if (slot >= %d)\n", max_slots); ! 3021: printf (" abort ();\n"); ! 3022: printf ("\n"); ! 3023: ! 3024: /* If more than one delay type, find out which type the delay insn is. */ ! 3025: ! 3026: if (num_delays > 1) ! 3027: { ! 3028: sprintf (str, "*delay_type", kind); ! 3029: attr = find_attr (str, 0); ! 3030: if (! attr) abort (); ! 3031: common_av = find_most_used (attr); ! 3032: ! 3033: printf (" insn = delay_insn;\n"); ! 3034: printf (" switch (recog_memoized (insn))\n"); ! 3035: printf (" {\n"); ! 3036: ! 3037: sprintf (str, " * %d;\n break;", max_slots); ! 3038: for (av = attr->first_value; av; av = av->next) ! 3039: if (av != common_av) ! 3040: write_attr_case (attr, av, 1, "slot +=", str, 4, true_rtx); ! 3041: ! 3042: write_attr_case (attr, common_av, 0, "slot +=", str, 4, true_rtx); ! 3043: printf (" }\n\n"); ! 3044: ! 3045: /* Ensure matched. Otherwise, shouldn't have been called. */ ! 3046: printf (" if (slot < %d)\n", max_slots); ! 3047: printf (" abort ();\n\n"); ! 3048: } ! 3049: ! 3050: /* If just one type of delay slot, write simple switch. */ ! 3051: if (num_delays == 1 && max_slots == 1) ! 3052: { ! 3053: printf (" insn = candidate_insn;\n"); ! 3054: printf (" switch (recog_memoized (insn))\n"); ! 3055: printf (" {\n"); ! 3056: ! 3057: attr = find_attr ("*delay_1_0", 0); ! 3058: if (! attr) abort (); ! 3059: common_av = find_most_used (attr); ! 3060: ! 3061: for (av = attr->first_value; av; av = av->next) ! 3062: if (av != common_av) ! 3063: write_attr_case (attr, av, 1, "return", ";", 4, true_rtx); ! 3064: ! 3065: write_attr_case (attr, common_av, 0, "return", ";", 4, true_rtx); ! 3066: printf (" }\n"); ! 3067: } ! 3068: ! 3069: else ! 3070: { ! 3071: /* Write a nested CASE. The first indicates which condition we need to ! 3072: test, and the inner CASE tests the condition. */ ! 3073: printf (" insn = candidate_insn;\n"); ! 3074: printf (" switch (slot)\n"); ! 3075: printf (" {\n"); ! 3076: ! 3077: for (delay = delays; delay; delay = delay->next) ! 3078: for (i = 0; i < XVECLEN (delay->def, 1); i += 3) ! 3079: { ! 3080: printf (" case %d:\n", ! 3081: (i / 3) + (num_delays == 1 ? 0 : delay->num * max_slots)); ! 3082: printf (" switch (recog_memoized (insn))\n"); ! 3083: printf ("\t{\n"); ! 3084: ! 3085: sprintf (str, "*%s_%d_%d", kind, delay->num, i / 3); ! 3086: attr = find_attr (str, 0); ! 3087: if (! attr) abort (); ! 3088: common_av = find_most_used (attr); ! 3089: ! 3090: for (av = attr->first_value; av; av = av->next) ! 3091: if (av != common_av) ! 3092: write_attr_case (attr, av, 1, "return", ";", 8, true_rtx); ! 3093: ! 3094: write_attr_case (attr, common_av, 0, "return", ";", 8, true_rtx); ! 3095: printf (" }\n"); ! 3096: } ! 3097: ! 3098: printf (" default:\n"); ! 3099: printf (" abort ();\n"); ! 3100: printf (" }\n"); ! 3101: } ! 3102: ! 3103: printf ("}\n\n"); ! 3104: } ! 3105: ! 3106: /* Write routines to compute conflict cost for function units. Then write a ! 3107: table describing the available function units. */ ! 3108: ! 3109: static void ! 3110: write_function_unit_info () ! 3111: { ! 3112: struct function_unit *unit; ! 3113: struct attr_desc *case_attr, *attr; ! 3114: struct attr_value *av, *common_av; ! 3115: rtx value; ! 3116: char *str; ! 3117: int using_case; ! 3118: int i; ! 3119: ! 3120: /* Write out conflict routines for function units. Don't bother writing ! 3121: one if there is only one busy value. */ ! 3122: ! 3123: for (unit = units; unit; unit = unit->next) ! 3124: { ! 3125: /* See if only one case exists and if there is a constant value for ! 3126: that case. If so, we don't need a function. */ ! 3127: str = (char *) xmalloc (strlen (unit->name) + 10); ! 3128: sprintf (str, "*%s_cases", unit->name); ! 3129: attr = find_attr (str, 0); ! 3130: if (! attr) abort (); ! 3131: value = find_single_value (attr); ! 3132: if (value && GET_CODE (value) == CONST_STRING) ! 3133: { ! 3134: sprintf (str, "*%s_case_%s", unit->name, XSTR (value, 0)); ! 3135: attr = find_attr (str, 0); ! 3136: if (! attr) abort (); ! 3137: value = find_single_value (attr); ! 3138: if (value && GET_CODE (value) == CONST_STRING) ! 3139: { ! 3140: unit->needs_conflict_function = 0; ! 3141: unit->default_cost = value; ! 3142: continue; ! 3143: } ! 3144: } ! 3145: ! 3146: /* The function first computes the case from the candidate insn. */ ! 3147: unit->needs_conflict_function = 1; ! 3148: unit->default_cost = make_numeric_value (0); ! 3149: ! 3150: printf ("static int\n"); ! 3151: printf ("%s_unit_conflict_cost (executing_insn, candidate_insn)\n", ! 3152: unit->name); ! 3153: printf (" rtx executing_insn;\n"); ! 3154: printf (" rtx candidate_insn;\n"); ! 3155: printf ("{\n"); ! 3156: printf (" rtx insn;\n"); ! 3157: printf (" int casenum;\n\n"); ! 3158: printf (" insn = candidate_insn;\n"); ! 3159: printf (" switch (recog_memoized (insn))\n"); ! 3160: printf (" {\n"); ! 3161: ! 3162: /* Write the `switch' statement to get the case value. */ ! 3163: sprintf (str, "*%s_cases", unit->name); ! 3164: case_attr = find_attr (str, 0); ! 3165: if (! case_attr) abort (); ! 3166: common_av = find_most_used (case_attr); ! 3167: ! 3168: for (av = case_attr->first_value; av; av = av->next) ! 3169: if (av != common_av) ! 3170: write_attr_case (case_attr, av, 1, ! 3171: "casenum =", ";", 4, unit->condexp); ! 3172: ! 3173: write_attr_case (case_attr, common_av, 0, ! 3174: "casenum =", ";", 4, unit->condexp); ! 3175: printf (" }\n\n"); ! 3176: ! 3177: /* Now write an outer switch statement on each case. Then write ! 3178: the tests on the executing function within each. */ ! 3179: printf (" insn = executing_insn;\n"); ! 3180: printf (" switch (casenum)\n"); ! 3181: printf (" {\n"); ! 3182: ! 3183: for (i = 0; i < unit->num_opclasses; i++) ! 3184: { ! 3185: /* Ensure using this case. */ ! 3186: using_case = 0; ! 3187: for (av = case_attr->first_value; av; av = av->next) ! 3188: if (av->num_insns ! 3189: && contained_in_p (make_numeric_value (i), av->value)) ! 3190: using_case = 1; ! 3191: ! 3192: if (! using_case) ! 3193: continue; ! 3194: ! 3195: printf (" case %d:\n", i); ! 3196: sprintf (str, "*%s_case_%d", unit->name, i); ! 3197: attr = find_attr (str, 0); ! 3198: if (! attr) abort (); ! 3199: ! 3200: /* If single value, just write it. */ ! 3201: value = find_single_value (attr); ! 3202: if (value) ! 3203: write_attr_set (attr, 6, value, "return", ";\n", true_rtx, -2); ! 3204: else ! 3205: { ! 3206: common_av = find_most_used (attr); ! 3207: printf (" switch (recog_memoized (insn))\n"); ! 3208: printf ("\t{\n"); ! 3209: ! 3210: for (av = attr->first_value; av; av = av->next) ! 3211: if (av != common_av) ! 3212: write_attr_case (attr, av, 1, ! 3213: "return", ";", 8, unit->condexp); ! 3214: ! 3215: write_attr_case (attr, common_av, 0, ! 3216: "return", ";", 8, unit->condexp); ! 3217: printf (" }\n\n"); ! 3218: } ! 3219: } ! 3220: ! 3221: printf (" }\n}\n\n"); ! 3222: } ! 3223: ! 3224: /* Now that all functions have been written, write the table describing ! 3225: the function units. The name is included for documenation purposes ! 3226: only. */ ! 3227: ! 3228: printf ("struct function_unit_desc function_units[] = {\n"); ! 3229: ! 3230: for (unit = units; unit; unit = unit->next) ! 3231: { ! 3232: printf (" {\"%s\", %d, %d, %d, %s, %s_unit_ready_cost, ", ! 3233: unit->name, 1 << unit->num, unit->multiplicity, ! 3234: unit->simultaneity, XSTR (unit->default_cost, 0), unit->name); ! 3235: ! 3236: if (unit->needs_conflict_function) ! 3237: printf ("%s_unit_conflict_cost", unit->name); ! 3238: else ! 3239: printf ("0"); ! 3240: ! 3241: printf ("}, \n"); ! 3242: } ! 3243: ! 3244: printf ("};\n\n"); ! 3245: } ! 3246: ! 3247: /* This page contains miscellaneous utility routines. */ ! 3248: ! 3249: /* Given a string, return the number of comma-separated elements in it. ! 3250: Return 0 for the null string. */ ! 3251: ! 3252: static int ! 3253: n_comma_elts (s) ! 3254: char *s; ! 3255: { ! 3256: int n; ! 3257: ! 3258: if (*s == '\0') ! 3259: return 0; ! 3260: ! 3261: for (n = 1; *s; s++) ! 3262: if (*s == ',') ! 3263: n++; ! 3264: ! 3265: return n; ! 3266: } ! 3267: ! 3268: /* Given a pointer to a (char *), return a malloc'ed string containing the ! 3269: next comma-separated element. Advance the pointer to after the string ! 3270: scanned, or the end-of-string. Return NULL if at end of string. */ ! 3271: ! 3272: static char * ! 3273: next_comma_elt (pstr) ! 3274: char **pstr; ! 3275: { ! 3276: char *out_str; ! 3277: char *p; ! 3278: ! 3279: if (**pstr == '\0') ! 3280: return NULL; ! 3281: ! 3282: /* Find end of string to compute length. */ ! 3283: for (p = *pstr; *p != ',' && *p != '\0'; p++) ! 3284: ; ! 3285: ! 3286: out_str = (char *) xmalloc (p - *pstr + 1); ! 3287: for (p = out_str; **pstr != ',' && **pstr != '\0'; (*pstr)++) ! 3288: *p++ = **pstr; ! 3289: ! 3290: *p++ = '\0'; ! 3291: if (**pstr == ',') ! 3292: (*pstr)++; ! 3293: ! 3294: return out_str; ! 3295: } ! 3296: ! 3297: /* Return a `struct attr_desc' pointer for a given named attribute. If CREATE ! 3298: is non-zero, build a new attribute, if one does not exist. */ ! 3299: ! 3300: static struct attr_desc * ! 3301: find_attr (name, create) ! 3302: char *name; ! 3303: int create; ! 3304: { ! 3305: struct attr_desc *attr; ! 3306: char *new_name; ! 3307: ! 3308: /* Before we resort to using `strcmp', see if the string address matches ! 3309: anywhere. In most cases, it should have been canonicalized to do so. */ ! 3310: if (name == alternative_name) ! 3311: return NULL; ! 3312: ! 3313: for (attr = attrs; attr; attr = attr->next) ! 3314: if (name == attr->name) ! 3315: return attr; ! 3316: ! 3317: /* Otherwise, do it the slow way. */ ! 3318: for (attr = attrs; attr; attr = attr->next) ! 3319: if (! strcmp (name, attr->name)) ! 3320: return attr; ! 3321: ! 3322: if (! create) ! 3323: return NULL; ! 3324: ! 3325: new_name = (char *) xmalloc (strlen (name) + 1); ! 3326: strcpy (new_name, name); ! 3327: ! 3328: attr = (struct attr_desc *) xmalloc (sizeof (struct attr_desc)); ! 3329: attr->name = new_name; ! 3330: attr->first_value = attr->default_val = NULL; ! 3331: attr->is_numeric = attr->is_special = 0; ! 3332: attr->next = attrs; ! 3333: attrs = attr; ! 3334: ! 3335: return attr; ! 3336: } ! 3337: ! 3338: /* Create internal attribute with the given default value. */ ! 3339: ! 3340: static void ! 3341: make_internal_attr (name, value, special) ! 3342: char *name; ! 3343: rtx value; ! 3344: int special; ! 3345: { ! 3346: struct attr_desc *attr; ! 3347: ! 3348: attr = find_attr (name, 1); ! 3349: if (attr->default_val) ! 3350: abort (); ! 3351: ! 3352: attr->is_numeric = 1; ! 3353: attr->is_special = special; ! 3354: attr->default_val = get_attr_value (value, attr, -2); ! 3355: } ! 3356: ! 3357: /* Find the most used value of an attribute. */ ! 3358: ! 3359: static struct attr_value * ! 3360: find_most_used (attr) ! 3361: struct attr_desc *attr; ! 3362: { ! 3363: struct attr_value *av; ! 3364: struct attr_value *most_used; ! 3365: int nuses; ! 3366: ! 3367: most_used = NULL; ! 3368: nuses = -1; ! 3369: ! 3370: for (av = attr->first_value; av; av = av->next) ! 3371: if (av->num_insns > nuses) ! 3372: nuses = av->num_insns, most_used = av; ! 3373: ! 3374: return most_used; ! 3375: } ! 3376: ! 3377: /* If an attribute only has a single value used, return it. Otherwise ! 3378: return NULL. */ ! 3379: ! 3380: static rtx ! 3381: find_single_value (attr) ! 3382: struct attr_desc *attr; ! 3383: { ! 3384: struct attr_value *av; ! 3385: rtx unique_value; ! 3386: ! 3387: unique_value = NULL; ! 3388: for (av = attr->first_value; av; av = av->next) ! 3389: if (av->num_insns) ! 3390: { ! 3391: if (unique_value) ! 3392: return NULL; ! 3393: else ! 3394: unique_value = av->value; ! 3395: } ! 3396: ! 3397: return unique_value; ! 3398: } ! 3399: ! 3400: /* Return (attr_value "n") */ ! 3401: ! 3402: static rtx ! 3403: make_numeric_value (n) ! 3404: int n; ! 3405: { ! 3406: static rtx int_values[20]; ! 3407: rtx exp; ! 3408: ! 3409: if (n < 0) ! 3410: abort (); ! 3411: ! 3412: if (n < 20 && int_values[n]) ! 3413: return int_values[n]; ! 3414: ! 3415: exp = rtx_alloc (CONST_STRING); ! 3416: XSTR (exp, 0) = (char *) xmalloc ((n < 1000 ? 4 ! 3417: : HOST_BITS_PER_INT * 3 / 10 + 3)); ! 3418: sprintf (XSTR (exp, 0), "%d", n); ! 3419: ! 3420: if (n < 20) ! 3421: int_values[n] = exp; ! 3422: ! 3423: return exp; ! 3424: } ! 3425: ! 3426: char * ! 3427: xrealloc (ptr, size) ! 3428: char *ptr; ! 3429: unsigned size; ! 3430: { ! 3431: char *result = (char *) realloc (ptr, size); ! 3432: if (!result) ! 3433: fatal ("virtual memory exhausted"); ! 3434: return result; ! 3435: } ! 3436: ! 3437: char * ! 3438: xmalloc (size) ! 3439: unsigned size; ! 3440: { ! 3441: register char *val = (char *) malloc (size); ! 3442: ! 3443: if (val == 0) ! 3444: fatal ("virtual memory exhausted"); ! 3445: return val; ! 3446: } ! 3447: ! 3448: static void ! 3449: fatal (s, a1, a2) ! 3450: char *s; ! 3451: { ! 3452: fprintf (stderr, "genattrtab: "); ! 3453: fprintf (stderr, s, a1, a2); ! 3454: fprintf (stderr, "\n"); ! 3455: exit (FATAL_EXIT_CODE); ! 3456: } ! 3457: ! 3458: /* More 'friendly' abort that prints the line and file. ! 3459: config.h can #define abort fancy_abort if you like that sort of thing. */ ! 3460: ! 3461: void ! 3462: fancy_abort () ! 3463: { ! 3464: fatal ("Internal gcc abort."); ! 3465: } ! 3466: ! 3467: int ! 3468: main (argc, argv) ! 3469: int argc; ! 3470: char **argv; ! 3471: { ! 3472: rtx desc; ! 3473: FILE *infile; ! 3474: extern rtx read_rtx (); ! 3475: register int c; ! 3476: struct attr_desc *attr; ! 3477: struct attr_value *av; ! 3478: struct insn_def *id; ! 3479: rtx tem; ! 3480: ! 3481: obstack_init (rtl_obstack); ! 3482: ! 3483: if (argc <= 1) ! 3484: fatal ("No input file name."); ! 3485: ! 3486: infile = fopen (argv[1], "r"); ! 3487: if (infile == 0) ! 3488: { ! 3489: perror (argv[1]); ! 3490: exit (FATAL_EXIT_CODE); ! 3491: } ! 3492: ! 3493: init_rtl (); ! 3494: ! 3495: /* Set up true and false rtx's */ ! 3496: true_rtx = rtx_alloc (CONST_INT); ! 3497: false_rtx = rtx_alloc (CONST_INT); ! 3498: XINT (true_rtx, 0) = 1; ! 3499: XINT (false_rtx, 0) = 0; ! 3500: RTX_UNCHANGING_P (true_rtx) = RTX_UNCHANGING_P (false_rtx) = 1; ! 3501: ! 3502: printf ("/* Generated automatically by the program `genattrtab'\n\ ! 3503: from the machine description file `md'. */\n\n"); ! 3504: ! 3505: /* Read the machine description. */ ! 3506: ! 3507: while (1) ! 3508: { ! 3509: c = read_skip_spaces (infile); ! 3510: if (c == EOF) ! 3511: break; ! 3512: ungetc (c, infile); ! 3513: ! 3514: desc = read_rtx (infile); ! 3515: if (GET_CODE (desc) == DEFINE_INSN ! 3516: || GET_CODE (desc) == DEFINE_PEEPHOLE ! 3517: || GET_CODE (desc) == DEFINE_ASM_ATTRIBUTES) ! 3518: gen_insn (desc); ! 3519: ! 3520: else if (GET_CODE (desc) == DEFINE_EXPAND) ! 3521: insn_code_number++, insn_index_number++; ! 3522: ! 3523: else if (GET_CODE (desc) == DEFINE_SPLIT) ! 3524: insn_code_number++, insn_index_number++; ! 3525: ! 3526: else if (GET_CODE (desc) == DEFINE_ATTR) ! 3527: { ! 3528: gen_attr (desc); ! 3529: insn_index_number++; ! 3530: } ! 3531: ! 3532: else if (GET_CODE (desc) == DEFINE_DELAY) ! 3533: { ! 3534: gen_delay (desc); ! 3535: insn_index_number++; ! 3536: } ! 3537: ! 3538: else if (GET_CODE (desc) == DEFINE_FUNCTION_UNIT) ! 3539: { ! 3540: gen_unit (desc); ! 3541: insn_index_number++; ! 3542: } ! 3543: } ! 3544: ! 3545: /* If we didn't have a DEFINE_ASM_ATTRIBUTES, make a null one. */ ! 3546: if (! got_define_asm_attributes) ! 3547: { ! 3548: tem = rtx_alloc (DEFINE_ASM_ATTRIBUTES); ! 3549: XVEC (tem, 0) = rtvec_alloc (0); ! 3550: gen_insn (tem); ! 3551: } ! 3552: ! 3553: /* Expand DEFINE_DELAY information into new attribute. */ ! 3554: if (num_delays) ! 3555: expand_delays (); ! 3556: ! 3557: /* Expand DEFINE_FUNCTION_UNIT information into new attributes. */ ! 3558: if (num_units) ! 3559: expand_units (); ! 3560: ! 3561: printf ("#include \"config.h\"\n"); ! 3562: printf ("#include \"rtl.h\"\n"); ! 3563: printf ("#include \"insn-config.h\"\n"); ! 3564: printf ("#include \"recog.h\"\n"); ! 3565: printf ("#include \"regs.h\"\n"); ! 3566: printf ("#include \"real.h\"\n"); ! 3567: printf ("#include \"output.h\"\n"); ! 3568: printf ("#include \"insn-attr.h\"\n"); ! 3569: printf ("\n"); ! 3570: printf ("#define operands recog_operand\n\n"); ! 3571: ! 3572: /* Make `insn_alternatives'. */ ! 3573: insn_alternatives = (int *) xmalloc (insn_code_number * sizeof (int)); ! 3574: for (id = defs; id; id = id->next) ! 3575: if (id->insn_code >= 0) ! 3576: insn_alternatives[id->insn_code] = (1 << id->num_alternatives) - 1; ! 3577: ! 3578: /* Prepare to write out attribute subroutines by checking everything stored ! 3579: away and building the attribute cases. */ ! 3580: ! 3581: check_defs (); ! 3582: for (attr = attrs; attr; attr = attr->next) ! 3583: { ! 3584: check_attr_value (attr->default_val->value, attr); ! 3585: fill_attr (attr); ! 3586: } ! 3587: ! 3588: /* Construct extra attributes for `length'. */ ! 3589: make_length_attrs (); ! 3590: ! 3591: /* Perform any possible optimizations to speed up compilation. */ ! 3592: optimize_attrs (); ! 3593: ! 3594: /* Now write out all the `gen_attr_...' routines. Do these before the ! 3595: special routines (specifically before write_function_unit_info), so ! 3596: that they get defined before they are used. */ ! 3597: ! 3598: for (attr = attrs; attr; attr = attr->next) ! 3599: { ! 3600: if (! attr->is_special) ! 3601: write_attr_get (attr); ! 3602: } ! 3603: ! 3604: /* Write out delay eligibility information, if DEFINE_DELAY present. ! 3605: (The function to compute the number of delay slots will be written ! 3606: below.) */ ! 3607: if (num_delays) ! 3608: { ! 3609: write_eligible_delay ("delay"); ! 3610: if (have_annul_true) ! 3611: write_eligible_delay ("annul_true"); ! 3612: if (have_annul_false) ! 3613: write_eligible_delay ("annul_false"); ! 3614: } ! 3615: ! 3616: /* Write out information about function units. */ ! 3617: if (num_units) ! 3618: write_function_unit_info (); ! 3619: ! 3620: fflush (stdout); ! 3621: exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); ! 3622: /* NOTREACHED */ ! 3623: return 0; ! 3624: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.