|
|
1.1 ! root 1: /* Optimize by combining instructions for GNU compiler. ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GNU CC. ! 5: ! 6: GNU CC is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the GNU CC General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: GNU CC, but only under the conditions described in the ! 15: GNU CC General Public License. A copy of this license is ! 16: supposed to have been given to you along with GNU CC so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: /* This module is essentially the "combiner" phase of the U. of Arizona ! 23: Portable Optimizer, but redone to work on our list-structured ! 24: representation for RTL instead of their string representation. ! 25: ! 26: The LOG_LINKS of each insn identify the most recent assignment ! 27: to each REG used in the insn. It is a list of previous insns, ! 28: each of which contains a SET for a REG that is used in this insn ! 29: and not used or set in between. LOG_LINKs never cross basic blocks. ! 30: They were set up by the preceding pass (lifetime analysis). ! 31: ! 32: We try to combine each pair of insns joined by a logical link. ! 33: We also try to combine triples of insns A, B and C when ! 34: C has a link back to B and B has a link back to A. ! 35: ! 36: LOG_LINKS does not have links for use of the CC0. They don't ! 37: need to, because the insn that sets the CC0 is always immediately ! 38: before the insn that tests it. So we always regard a branch ! 39: insn as having a logical link to the preceding insn. ! 40: ! 41: We check (with use_crosses_set_p) to avoid combining in such a way ! 42: as to move a computation to a place where its value would be different. ! 43: ! 44: Combination is done by mathematically substituting the previous ! 45: insn(s) values for the regs they set into the expressions in ! 46: the later insns that refer to these regs. If the result is a valid insn ! 47: for our target machine, according to the machine description, ! 48: we install it, delete the earlier insns, and update the data flow ! 49: information (LOG_LINKS and REG_NOTES) for what we did. ! 50: ! 51: To simplify substitution, we combine only when the earlier insn(s) ! 52: consist of only a single assignment. To simplify updating afterward, ! 53: we never combine when a subroutine call appears in the middle. ! 54: ! 55: Since we do not represent assignments to CC0 explicitly except when that ! 56: is all an insn does, there is no LOG_LINKS entry in an insn that uses ! 57: the condition code for the insn that set the condition code. ! 58: Fortunately, these two insns must be consecutive. ! 59: Therefore, every JUMP_INSN is taken to have an implicit logical link ! 60: to the preceding insn. This is not quite right, since non-jumps can ! 61: also use the condition code; but in practice such insns would not ! 62: combine anyway. */ ! 63: ! 64: #include "config.h" ! 65: #include "rtl.h" ! 66: #include "regs.h" ! 67: #include "basic-block.h" ! 68: #include "insn-config.h" ! 69: #include "recog.h" ! 70: ! 71: #define max(A,B) ((A) > (B) ? (A) : (B)) ! 72: #define min(A,B) ((A) < (B) ? (A) : (B)) ! 73: ! 74: /* Number of attempts to combine instructions in this function. */ ! 75: ! 76: static int combine_attempts; ! 77: ! 78: /* Number of attempts that got as far as substitution in this function. */ ! 79: ! 80: static int combine_merges; ! 81: ! 82: /* Number of instructions combined with added SETs in this function. */ ! 83: ! 84: static int combine_extras; ! 85: ! 86: /* Number of instructions combined in this function. */ ! 87: ! 88: static int combine_successes; ! 89: ! 90: /* Totals over entire compilation. */ ! 91: ! 92: static int total_attempts, total_merges, total_extras, total_successes; ! 93: ! 94: ! 95: /* Vector mapping INSN_UIDs to cuids. ! 96: The cuids are like uids but increase monononically always. ! 97: Combine always uses cuids so that it can compare them. ! 98: But actually renumbering the uids, which we used to do, ! 99: proves to be a bad idea because it makes it hard to compare ! 100: the dumps produced by earlier passes with those from later passes. */ ! 101: ! 102: static short *uid_cuid; ! 103: ! 104: /* Get the cuid of an insn. */ ! 105: ! 106: #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)]) ! 107: ! 108: ! 109: /* Record last point of death of (hard or pseudo) register n. */ ! 110: ! 111: static rtx *reg_last_death; ! 112: ! 113: /* Record last point of modification of (hard or pseudo) register n. */ ! 114: ! 115: static rtx *reg_last_set; ! 116: ! 117: /* Record the cuid of the last insn that invalidated memory ! 118: (anything that writes memory, and subroutine calls). */ ! 119: ! 120: static int mem_last_set; ! 121: ! 122: /* Record the cuid of the last CALL_INSN ! 123: so we can tell whether a potential combination crosses any calls. */ ! 124: ! 125: static int last_call_cuid; ! 126: ! 127: /* When `subst' is called, this is the insn that is being modified ! 128: (by combining in a previous insn). The PATTERN of this insn ! 129: is still the old pattern partially modified and it should not be ! 130: looked at, but this may be used to examine the successors of the insn ! 131: to judge whether a simplification is valid. */ ! 132: ! 133: static rtx subst_insn; ! 134: ! 135: /* Record one modification to rtl structure ! 136: to be undone by storing old_contents into *where. */ ! 137: ! 138: struct undo ! 139: { ! 140: rtx *where; ! 141: rtx old_contents; ! 142: }; ! 143: ! 144: /* Record a bunch of changes to be undone, up to MAX_UNDO of them. ! 145: num_undo says how many are currently recorded. ! 146: storage is nonzero if we must undo the allocation of new storage. ! 147: The value of storage is what to pass to obfree. */ ! 148: ! 149: #define MAX_UNDO 10 ! 150: ! 151: struct undobuf ! 152: { ! 153: int num_undo; ! 154: char *storage; ! 155: struct undo undo[MAX_UNDO]; ! 156: }; ! 157: ! 158: static struct undobuf undobuf; ! 159: ! 160: static void move_deaths (); ! 161: static void remove_death (); ! 162: static void record_dead_and_set_regs (); ! 163: int regno_dead_p (); ! 164: static int reg_set_in_range_p (); ! 165: static int use_crosses_set_p (); ! 166: static rtx subst (); ! 167: static void undo_all (); ! 168: static void add_links (); ! 169: static void add_incs (); ! 170: static int adjacent_insns_p (); ! 171: static rtx simplify_and_const_int (); ! 172: static rtx gen_lowpart_for_combine (); ! 173: static void simplify_set_cc0_and (); ! 174: ! 175: /* Main entry point for combiner. F is the first insn of the function. ! 176: NREGS is the first unused pseudo-reg number. */ ! 177: ! 178: void ! 179: combine_instructions (f, nregs) ! 180: rtx f; ! 181: int nregs; ! 182: { ! 183: register rtx insn; ! 184: register int i; ! 185: register rtx links, nextlinks; ! 186: rtx prev; ! 187: ! 188: combine_attempts = 0; ! 189: combine_merges = 0; ! 190: combine_extras = 0; ! 191: combine_successes = 0; ! 192: ! 193: reg_last_death = (rtx *) alloca (nregs * sizeof (rtx)); ! 194: reg_last_set = (rtx *) alloca (nregs * sizeof (rtx)); ! 195: bzero (reg_last_death, nregs * sizeof (rtx)); ! 196: bzero (reg_last_set, nregs * sizeof (rtx)); ! 197: ! 198: init_recog (); ! 199: ! 200: /* Compute maximum uid value so uid_cuid can be allocated. */ ! 201: ! 202: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn)) ! 203: if (INSN_UID (insn) > i) ! 204: i = INSN_UID (insn); ! 205: ! 206: uid_cuid = (short *) alloca ((i + 1) * sizeof (short)); ! 207: ! 208: /* Compute the mapping from uids to cuids. ! 209: Cuids are numbers assigned to insns, like uids, ! 210: except that cuids increase monotonically through the code. */ ! 211: ! 212: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn)) ! 213: INSN_CUID (insn) = ++i; ! 214: ! 215: /* Now scan all the insns in forward order. */ ! 216: ! 217: last_call_cuid = 0; ! 218: mem_last_set = 0; ! 219: prev = 0; ! 220: ! 221: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 222: { ! 223: if (GET_CODE (insn) == INSN ! 224: || GET_CODE (insn) == CALL_INSN ! 225: || GET_CODE (insn) == JUMP_INSN) ! 226: { ! 227: retry: ! 228: /* Try this insn with each insn it links back to. */ ! 229: ! 230: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! 231: if (try_combine (insn, XEXP (links, 0), 0)) ! 232: goto retry; ! 233: ! 234: /* Try each sequence of three linked insns ending with this one. */ ! 235: ! 236: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! 237: if (GET_CODE (XEXP (links, 0)) != NOTE) ! 238: for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks; ! 239: nextlinks = XEXP (nextlinks, 1)) ! 240: if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0))) ! 241: goto retry; ! 242: ! 243: /* Try to combine a jump insn that uses CC0 ! 244: with a preceding insn that sets CC0, and maybe with its ! 245: logical predecessor as well. ! 246: This is how we make decrement-and-branch insns. ! 247: We need this special code because data flow connections ! 248: via CC0 do not get entered in LOG_LINKS. */ ! 249: ! 250: if (GET_CODE (insn) == JUMP_INSN ! 251: && prev != 0 ! 252: && GET_CODE (prev) == INSN ! 253: && GET_CODE (PATTERN (prev)) == SET ! 254: && GET_CODE (SET_DEST (PATTERN (prev))) == CC0) ! 255: { ! 256: if (try_combine (insn, prev, 0)) ! 257: goto retry; ! 258: ! 259: if (GET_CODE (prev) != NOTE) ! 260: for (nextlinks = LOG_LINKS (prev); nextlinks; ! 261: nextlinks = XEXP (nextlinks, 1)) ! 262: if (try_combine (insn, prev, XEXP (nextlinks, 0))) ! 263: goto retry; ! 264: } ! 265: #if 0 ! 266: /* Turned off because on 68020 it takes four insns to make ! 267: something like (a[b / 32] & (1 << (31 - (b % 32)))) != 0 ! 268: that could actually be optimized, and that's an unlikely piece of code. */ ! 269: /* If an insn gets or sets a bit field, try combining it ! 270: with two different insns whose results it uses. */ ! 271: if (GET_CODE (insn) == INSN ! 272: && GET_CODE (PATTERN (insn)) == SET ! 273: && (GET_CODE (SET_DEST (PATTERN (insn))) == ZERO_EXTRACT ! 274: || GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT ! 275: || GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT ! 276: || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT)) ! 277: { ! 278: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! 279: if (GET_CODE (XEXP (links, 0)) != NOTE) ! 280: for (nextlinks = XEXP (links, 1); nextlinks; ! 281: nextlinks = XEXP (nextlinks, 1)) ! 282: if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0))) ! 283: goto retry; ! 284: } ! 285: #endif ! 286: record_dead_and_set_regs (insn); ! 287: prev = insn; ! 288: } ! 289: else if (GET_CODE (insn) != NOTE) ! 290: prev = 0; ! 291: } ! 292: total_attempts += combine_attempts; ! 293: total_merges += combine_merges; ! 294: total_extras += combine_extras; ! 295: total_successes += combine_successes; ! 296: } ! 297: ! 298: /* Try to combine the insns I1 and I2 into I3. ! 299: Here I1 appears earlier than I2, which is earlier than I3. ! 300: I1 can be zero; then we combine just I2 into I3. ! 301: ! 302: Return 1 if successful; if that happens, I1 and I2 are pseudo-deleted ! 303: by turning them into NOTEs, and I3 is modified. ! 304: Return 0 if the combination does not work. Then nothing is changed. */ ! 305: ! 306: static int ! 307: try_combine (i3, i2, i1) ! 308: register rtx i3, i2, i1; ! 309: { ! 310: register rtx newpat; ! 311: int added_sets_1 = 0; ! 312: int added_sets_2 = 0; ! 313: int total_sets; ! 314: int i2_is_used; ! 315: register rtx link; ! 316: int insn_code_number; ! 317: int recog_flags = 0; ! 318: rtx i2dest, i2src; ! 319: rtx i1dest, i1src; ! 320: ! 321: combine_attempts++; ! 322: ! 323: /* Don't combine with something already used up by combination. */ ! 324: ! 325: if (GET_CODE (i2) == NOTE ! 326: || (i1 && GET_CODE (i1) == NOTE)) ! 327: return 0; ! 328: ! 329: /* Don't combine across a CALL_INSN, because that would possibly ! 330: change whether the life span of some REGs crosses calls or not, ! 331: and it is a pain to update that information. */ ! 332: ! 333: if (INSN_CUID (i2) < last_call_cuid ! 334: || (i1 && INSN_CUID (i1) < last_call_cuid)) ! 335: return 0; ! 336: ! 337: /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0. ! 338: That REG must be either set or dead by the final instruction ! 339: (so that we can safely forget about setting it). ! 340: Also test use_crosses_set_p to make sure that the value ! 341: that is to be substituted for the register ! 342: does not use any registers whose values alter in between. ! 343: Do not try combining with moves from one register to another ! 344: since it is better to let them be tied by register allocation. ! 345: ! 346: A set of a SUBREG is considered as if it were a set from ! 347: SUBREG. Thus, (SET (SUBREG:X (REG:Y...)) (something:X...)) ! 348: is handled by substituting (SUBREG:Y (something:X...)) for (REG:Y...). */ ! 349: ! 350: if (GET_CODE (PATTERN (i2)) != SET) ! 351: return 0; ! 352: i2dest = SET_DEST (PATTERN (i2)); ! 353: i2src = SET_SRC (PATTERN (i2)); ! 354: if (GET_CODE (i2dest) == SUBREG) ! 355: { ! 356: i2dest = SUBREG_REG (i2dest); ! 357: i2src = gen_rtx (SUBREG, GET_MODE (i2dest), i2src, 0); ! 358: } ! 359: if (GET_CODE (i2dest) != CC0 ! 360: && (GET_CODE (i2dest) != REG ! 361: || GET_CODE (i2src) == REG ! 362: || use_crosses_set_p (i2src, INSN_CUID (i2)))) ! 363: return 0; ! 364: ! 365: if (i1 != 0) ! 366: { ! 367: if (GET_CODE (PATTERN (i1)) != SET) ! 368: return 0; ! 369: i1dest = SET_DEST (PATTERN (i1)); ! 370: i1src = SET_SRC (PATTERN (i1)); ! 371: if (GET_CODE (i1dest) == SUBREG) ! 372: { ! 373: i1dest = SUBREG_REG (i1dest); ! 374: i1src = gen_rtx (SUBREG, GET_MODE (i1dest), i1src, 0); ! 375: } ! 376: if (GET_CODE (i1dest) != CC0 ! 377: && (GET_CODE (i1dest) != REG ! 378: || GET_CODE (i1src) == REG ! 379: || use_crosses_set_p (i1src, INSN_CUID (i1)))) ! 380: return 0; ! 381: } ! 382: ! 383: /* If I1 or I2 contains an autoincrement or autodecrement, ! 384: make sure that register is not used between there and I3. ! 385: Also insist that I3 not be a jump; if it were one ! 386: and the incremented register were spilled, we would lose. */ ! 387: for (link = REG_NOTES (i2); link; link = XEXP (link, 1)) ! 388: if ((enum reg_note) GET_MODE (link) == REG_INC) ! 389: if (GET_CODE (i3) == JUMP_INSN ! 390: || reg_used_between_p (XEXP (link, 0), i2, i3)) ! 391: return 0; ! 392: ! 393: if (i1) ! 394: for (link = REG_NOTES (i1); link; link = XEXP (link, 1)) ! 395: if ((enum reg_note) GET_MODE (link) == REG_INC) ! 396: if (GET_CODE (i3) == JUMP_INSN ! 397: || reg_used_between_p (XEXP (link, 0), i1, i3)) ! 398: return 0; ! 399: ! 400: /* See if the SETs in i1 or i2 need to be kept around in the merged ! 401: instruction: whenever the value set there is still needed past i3. */ ! 402: added_sets_2 = (GET_CODE (i2dest) != CC0 ! 403: && ! dead_or_set_p (i3, i2dest)); ! 404: if (i1) ! 405: added_sets_1 = ! (dead_or_set_p (i3, i1dest) ! 406: || dead_or_set_p (i2, i1dest)); ! 407: ! 408: combine_merges++; ! 409: ! 410: undobuf.num_undo = 0; ! 411: undobuf.storage = 0; ! 412: ! 413: /* Substitute in the latest insn for the regs set by the earlier ones. */ ! 414: ! 415: subst_insn = i3; ! 416: newpat = subst (PATTERN (i3), i2dest, i2src); ! 417: /* Record whether i2's body now appears within i3's body. */ ! 418: i2_is_used = undobuf.num_undo; ! 419: ! 420: if (i1) ! 421: newpat = subst (newpat, i1dest, i1src); ! 422: ! 423: if (GET_CODE (PATTERN (i3)) == SET ! 424: && SET_DEST (PATTERN (i3)) == cc0_rtx ! 425: && GET_CODE (SET_SRC (PATTERN (i3))) == AND ! 426: && next_insn_tests_no_inequality (i3)) ! 427: simplify_set_cc0_and (i3); ! 428: ! 429: /* If the actions of the earler insns must be kept ! 430: in addition to substituting them into the latest one, ! 431: we must make a new PARALLEL for the latest insn ! 432: to hold additional the SETs. */ ! 433: ! 434: if (added_sets_1 || added_sets_2) ! 435: { ! 436: combine_extras++; ! 437: ! 438: /* Arrange to free later what we allocate now ! 439: if we don't accept this combination. */ ! 440: if (!undobuf.storage) ! 441: undobuf.storage = (char *) oballoc (0); ! 442: ! 443: if (GET_CODE (newpat) == PARALLEL) ! 444: { ! 445: total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2; ! 446: newpat = gen_rtx (PARALLEL, VOIDmode, ! 447: gen_rtvec_v (total_sets, ! 448: &XVECEXP (newpat, 0, 0))); ! 449: } ! 450: else ! 451: { ! 452: total_sets = 1 + added_sets_1 + added_sets_2; ! 453: newpat = gen_rtx (PARALLEL, VOIDmode, ! 454: gen_rtvec (total_sets, newpat)); ! 455: } ! 456: if (added_sets_1) ! 457: { ! 458: XVECEXP (newpat, 0, --total_sets) = PATTERN (i1); ! 459: } ! 460: if (added_sets_2) ! 461: { ! 462: /* If there is no I1, use I2's body as is. */ ! 463: if (i1 == 0 ! 464: /* If I2 was stuck into I3, then anything within it has ! 465: already had I1 substituted into it when that was done to I3. */ ! 466: || i2_is_used) ! 467: { ! 468: XVECEXP (newpat, 0, --total_sets) = PATTERN (i2); ! 469: } ! 470: else ! 471: XVECEXP (newpat, 0, --total_sets) ! 472: = subst (PATTERN (i2), i1dest, i1src); ! 473: } ! 474: } ! 475: ! 476: /* Is the result of combination a valid instruction? */ ! 477: insn_code_number = recog (newpat, i3); ! 478: ! 479: if (insn_code_number >= 0) ! 480: { ! 481: /* Yes. Install it. */ ! 482: register int regno; ! 483: INSN_CODE (i3) = insn_code_number; ! 484: PATTERN (i3) = newpat; ! 485: /* Most REGs that previously died in I2 now die in I3. */ ! 486: move_deaths (i2src, INSN_CUID (i2), i3); ! 487: if (GET_CODE (i2dest) == REG) ! 488: { ! 489: /* If the reg formerly set in I2 died only once and that was in I3, ! 490: zero its use count so it won't make `reload' do any work. */ ! 491: regno = REGNO (i2dest); ! 492: if (! added_sets_2) ! 493: reg_n_sets[regno]--; ! 494: if (reg_n_sets[regno] == 0 && regno_dead_p (regno, i3)) ! 495: reg_n_refs[regno] = 0; ! 496: /* If a ref to REGNO was substituted into I3 from I2, ! 497: then it still dies there if it previously did. ! 498: Otherwise either REGNO never did die in I3 so remove_death is safe ! 499: or this entire life of REGNO is gone so remove its death. */ ! 500: if (!added_sets_2 ! 501: && ! reg_mentioned_p (i2dest, PATTERN (i3))) ! 502: remove_death (regno, i3); ! 503: } ! 504: /* The data flowing into I2 now flows into I3. ! 505: But we cannot always move I2's LOG_LINKS into I3, ! 506: since they must go to a setting of a REG from the ! 507: first use following. If I2 was the first use following a set, ! 508: I3 is now a use, but it is not the first use ! 509: if some instruction between I2 and I3 is also a use. ! 510: Here, for simplicity, we move the links only if ! 511: there are no real insns between I2 and I3. */ ! 512: if (adjacent_insns_p (i2, i3)) ! 513: add_links (i3, LOG_LINKS (i2)); ! 514: /* Any registers previously autoincremented in I2 ! 515: are now incremented in I3. */ ! 516: add_incs (i3, REG_NOTES (i2)); ! 517: /* Get rid of I2. */ ! 518: LOG_LINKS (i2) = 0; ! 519: PUT_CODE (i2, NOTE); ! 520: NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED; ! 521: NOTE_SOURCE_FILE (i2) = 0; ! 522: if (i1) ! 523: { ! 524: /* Likewise, merge the info from I1 and get rid of it. */ ! 525: move_deaths (i1src, INSN_CUID (i1), i3); ! 526: if (GET_CODE (i1dest) == REG) ! 527: { ! 528: regno = REGNO (i1dest); ! 529: if (! added_sets_1) ! 530: reg_n_sets[regno]--; ! 531: if (reg_n_sets[regno] == 0 && regno_dead_p (regno, i3)) ! 532: reg_n_refs[regno] = 0; ! 533: /* If a ref to REGNO was substituted into I3 from I1, ! 534: then it still dies there if it previously did. ! 535: Else either REGNO never did die in I3 so remove_death is safe ! 536: or this entire life of REGNO is gone so remove its death. */ ! 537: if (! added_sets_1 ! 538: && ! reg_mentioned_p (i1dest, PATTERN (i3))) ! 539: remove_death (regno, i3); ! 540: } ! 541: if (adjacent_insns_p (i2, i3)) ! 542: add_links (i3, LOG_LINKS (i1)); ! 543: add_incs (i3, REG_NOTES (i1)); ! 544: LOG_LINKS (i1) = 0; ! 545: PUT_CODE (i1, NOTE); ! 546: NOTE_LINE_NUMBER (i1) = NOTE_INSN_DELETED; ! 547: NOTE_SOURCE_FILE (i1) = 0; ! 548: } ! 549: ! 550: combine_successes++; ! 551: return 1; ! 552: } ! 553: ! 554: /* Failure: change I3 back the way it was. */ ! 555: undo_all (); ! 556: ! 557: return 0; ! 558: } ! 559: ! 560: /* Undo all the modifications recorded in undobuf. */ ! 561: ! 562: static void ! 563: undo_all () ! 564: { ! 565: register int i; ! 566: if (undobuf.num_undo > MAX_UNDO) ! 567: undobuf.num_undo = MAX_UNDO; ! 568: for (i = undobuf.num_undo - 1; i >= 0; i--) ! 569: *undobuf.undo[i].where = undobuf.undo[i].old_contents; ! 570: if (undobuf.storage) ! 571: obfree (undobuf.storage); ! 572: undobuf.num_undo = 0; ! 573: undobuf.storage = 0; ! 574: } ! 575: ! 576: /* Throughout X, replace FROM with TO, and return the result. ! 577: The result is TO if X is FROM; ! 578: otherwise the result is X, but its contents may have been modified. ! 579: If they were modified, a record was made in undobuf so that ! 580: undo_all will (among other things) return X to its original state. ! 581: ! 582: If the number of changes necessary is too much to record to undo, ! 583: the excess changes are not made, so the result is invalid. ! 584: The changes already made can still be undone. ! 585: undobuf.num_undo is incremented for such changes, so by testing that ! 586: the caller can tell whether the result is valid. */ ! 587: ! 588: static rtx ! 589: subst (x, from, to) ! 590: register rtx x, from, to; ! 591: { ! 592: register char *fmt; ! 593: register int len, i; ! 594: register enum rtx_code code; ! 595: ! 596: /* THIS_TO is used to replace FROM if it appears exactly one ! 597: level down in X. Simplifications often work by changing ! 598: THIS_TO after observing that FROM appears in a specific way ! 599: one level down in X. Since only THIS_TO is changed, and TO ! 600: is left alone, further occurrences of FROM within the operands ! 601: of X are replaced normally. */ ! 602: rtx this_to; ! 603: ! 604: if (x == from) ! 605: return to; ! 606: ! 607: code = GET_CODE (x); ! 608: this_to = to; ! 609: ! 610: /* A little bit of algebraic simplification here. */ ! 611: switch (code) ! 612: { ! 613: /* This case has no effect except to speed things up. */ ! 614: case REG: ! 615: case CONST_INT: ! 616: case CONST: ! 617: case SYMBOL_REF: ! 618: case LABEL_REF: ! 619: case PC: ! 620: case CC0: ! 621: return x; ! 622: ! 623: case NOT: ! 624: case NEG: ! 625: /* Don't let substitution introduce double-negatives. */ ! 626: if (XEXP (x, 0) == from ! 627: && GET_CODE (to) == code) ! 628: return XEXP (to, 0); ! 629: break; ! 630: ! 631: case PLUS: ! 632: /* In (plus <foo> (ashift <bar> <n>)) ! 633: change the shift to a multiply so we can recognize ! 634: scaled indexed addresses. */ ! 635: if ((XEXP (x, 0) == from ! 636: || XEXP (x, 1) == from) ! 637: && GET_CODE (to) == ASHIFT ! 638: && GET_CODE (XEXP (to, 1)) == CONST_INT) ! 639: { ! 640: if (!undobuf.storage) ! 641: undobuf.storage = (char *) oballoc (0); ! 642: this_to = gen_rtx (MULT, GET_MODE (to), ! 643: XEXP (to, 0), ! 644: gen_rtx (CONST_INT, VOIDmode, ! 645: 1 << INTVAL (XEXP (to, 1)))); ! 646: } ! 647: /* If we have something (putative index) being added to a sum, ! 648: associate it so that any constant term is outermost. ! 649: That's because that's the way indexed addresses are ! 650: now supposed to appear. */ ! 651: if (((XEXP (x, 0) == from && GET_CODE (XEXP (x, 1)) == PLUS) ! 652: || (XEXP (x, 1) == from && GET_CODE (XEXP (x, 0)) == PLUS)) ! 653: || ! 654: ((XEXP (x, 0) == from || XEXP (x, 1) == from) ! 655: && GET_CODE (this_to) == PLUS)) ! 656: { ! 657: rtx offset = 0, base, index; ! 658: if (GET_CODE (this_to) != PLUS) ! 659: { ! 660: index = this_to; ! 661: base = XEXP (x, 0) == from ? XEXP (x, 1) : XEXP (x, 0); ! 662: } ! 663: else ! 664: { ! 665: index = XEXP (x, 0) == from ? XEXP (x, 1) : XEXP (x, 0); ! 666: base = this_to; ! 667: } ! 668: if (CONSTANT_ADDRESS_P (XEXP (base, 0))) ! 669: { ! 670: offset = XEXP (base, 0); ! 671: base = XEXP (base, 1); ! 672: } ! 673: else if (CONSTANT_ADDRESS_P (XEXP (base, 1))) ! 674: { ! 675: offset = XEXP (base, 1); ! 676: base = XEXP (base, 0); ! 677: } ! 678: if (offset != 0) ! 679: { ! 680: if (!undobuf.storage) ! 681: undobuf.storage = (char *) oballoc (0); ! 682: return gen_rtx (PLUS, GET_MODE (index), offset, ! 683: gen_rtx (PLUS, GET_MODE (index), ! 684: index, base)); ! 685: } ! 686: } ! 687: break; ! 688: ! 689: case MINUS: ! 690: /* Can simplify (minus:VOIDmode (zero/sign_extend FOO) CONST) ! 691: (which is a compare instruction, not a subtract instruction) ! 692: to (minus FOO CONST) if CONST fits in FOO's mode ! 693: and we are only testing equality. ! 694: In fact, this is valid for zero_extend if what follows is an ! 695: unsigned comparison, and for sign_extend with a signed comparison. */ ! 696: if (GET_MODE (x) == VOIDmode ! 697: && XEXP (x, 0) == from ! 698: && (GET_CODE (to) == ZERO_EXTEND || GET_CODE (to) == SIGN_EXTEND) ! 699: && next_insn_tests_no_inequality (subst_insn) ! 700: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 701: && ((unsigned) INTVAL (XEXP (x, 1)) ! 702: < (1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (XEXP (to, 0))))))) ! 703: this_to = XEXP (to, 0); ! 704: break; ! 705: ! 706: case EQ: ! 707: case NE: ! 708: /* If comparing a subreg against zero, discard the subreg. */ ! 709: if (XEXP (x, 0) == from ! 710: && GET_CODE (to) == SUBREG ! 711: && SUBREG_WORD (to) == 0 ! 712: && XEXP (x, 1) == const0_rtx) ! 713: this_to = SUBREG_REG (to); ! 714: ! 715: /* If comparing a ZERO_EXTRACT against zero, ! 716: canonicalize to a SIGN_EXTRACT, ! 717: since the two are equivalent here. */ ! 718: if (XEXP (x, 0) == from ! 719: && GET_CODE (this_to) == ZERO_EXTRACT ! 720: && XEXP (x, 1) == const0_rtx) ! 721: { ! 722: if (!undobuf.storage) ! 723: undobuf.storage = (char *) oballoc (0); ! 724: this_to = gen_rtx (SIGN_EXTRACT, GET_MODE (this_to), ! 725: XEXP (this_to, 0), XEXP (this_to, 1), ! 726: XEXP (this_to, 2)); ! 727: } ! 728: /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0), ! 729: arrange to return (EQ (SIGN_EXTRACT y 1 x) 0), ! 730: which is what jump-on-bit instructions are written with. */ ! 731: else if (XEXP (x, 1) == const0_rtx ! 732: && GET_CODE (XEXP (x, 0)) == AND ! 733: && (XEXP (XEXP (x, 0), 0) == from ! 734: || XEXP (XEXP (x, 0), 1) == from) ! 735: && GET_CODE (this_to) == ASHIFT ! 736: && XEXP (this_to, 0) == const1_rtx) ! 737: { ! 738: register rtx y = XEXP (XEXP (x, 0), ! 739: XEXP (XEXP (x, 0), 0) == from); ! 740: if (!undobuf.storage) ! 741: undobuf.storage = (char *) oballoc (0); ! 742: this_to = gen_rtx (SIGN_EXTRACT, GET_MODE (this_to), ! 743: y, ! 744: const1_rtx, XEXP (this_to, 1)); ! 745: from = XEXP (x, 0); ! 746: } ! 747: ! 748: break; ! 749: ! 750: case ZERO_EXTEND: ! 751: if (XEXP (x, 0) == from ! 752: && GET_CODE (to) == ZERO_EXTEND) ! 753: this_to = XEXP (to, 0); ! 754: /* Zero-extending the result of an and with a constant can be done ! 755: with a wider and. */ ! 756: if (XEXP (x, 0) == from ! 757: && GET_CODE (to) == AND ! 758: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 759: && (GET_CODE (XEXP (to, 0)) == REG ! 760: || offsetable_address_p (XEXP (to, 0))) ! 761: /* Avoid getting wrong result if the constant has high bits set ! 762: that are irrelevant in the narrow mode where it is being used. */ ! 763: && ((INTVAL (XEXP (to, 1)) ! 764: & (-1 << (GET_MODE_SIZE (GET_MODE (to)) * BITS_PER_UNIT))) ! 765: == 0)) ! 766: { ! 767: if (!undobuf.storage) ! 768: undobuf.storage = (char *) oballoc (0); ! 769: return gen_rtx (AND, GET_MODE (x), ! 770: gen_lowpart (GET_MODE (x), XEXP (to, 0)), ! 771: XEXP (to, 1)); ! 772: } ! 773: break; ! 774: ! 775: case SIGN_EXTEND: ! 776: if (XEXP (x, 0) == from ! 777: && GET_CODE (to) == SIGN_EXTEND) ! 778: this_to = XEXP (to, 0); ! 779: /* Sign-extending the result of an and with a constant can be done ! 780: with a wider and, provided the high bit of the constant is 0. */ ! 781: if (XEXP (x, 0) == from ! 782: && GET_CODE (to) == AND ! 783: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 784: && (GET_CODE (XEXP (to, 0)) == REG ! 785: || offsetable_address_p (XEXP (to, 0))) ! 786: && ((INTVAL (XEXP (to, 1)) ! 787: & (-1 << (GET_MODE_SIZE (GET_MODE (to)) * BITS_PER_UNIT - 1))) ! 788: == 0)) ! 789: { ! 790: if (!undobuf.storage) ! 791: undobuf.storage = (char *) oballoc (0); ! 792: return gen_rtx (AND, GET_MODE (x), ! 793: gen_lowpart (GET_MODE (x), XEXP (to, 0)), ! 794: XEXP (to, 1)); ! 795: } ! 796: break; ! 797: ! 798: case SET: ! 799: /* In (set (zero-extract <x> <1> <y>) (and <foo> <1>)) ! 800: the `and' can be deleted. This can happen when storing a bit ! 801: that came from a set-flag insn followed by masking to one bit. ! 802: There is probably no need to optimize other field widths similarly ! 803: because on machines with bit-field insns `and' is not needed ! 804: to extract the fields. */ ! 805: if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT ! 806: && XEXP (XEXP (x, 0), 1) == const1_rtx ! 807: && XEXP (x, 1) == from ! 808: && GET_CODE (to) == AND ! 809: && XEXP (to, 1) == const1_rtx) ! 810: { ! 811: this_to = XEXP (to, 0); ! 812: } ! 813: break; ! 814: ! 815: case AND: ! 816: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 817: { ! 818: rtx tem = simplify_and_const_int (x, from, to); ! 819: if (tem) ! 820: return tem; ! 821: } ! 822: break; ! 823: ! 824: case FLOAT: ! 825: /* (float (sign_extend <X>)) = (float <X>). */ ! 826: if (XEXP (x, 0) == from ! 827: && GET_CODE (to) == SIGN_EXTEND) ! 828: this_to = XEXP (to, 0); ! 829: break; ! 830: ! 831: case ZERO_EXTRACT: ! 832: /* Extracting a single bit from the result of a shift: ! 833: see which bit it was before the shift and extract that directly. */ ! 834: if (XEXP (x, 0) == from ! 835: && (GET_CODE (to) == ASHIFTRT || GET_CODE (to) == LSHIFTRT ! 836: || GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT) ! 837: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 838: && XEXP (x, 1) == const1_rtx ! 839: && GET_CODE (XEXP (x, 2)) == CONST_INT) ! 840: { ! 841: int shift = INTVAL (XEXP (to, 1)); ! 842: int newpos; ! 843: if (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT) ! 844: shift = - shift; ! 845: #ifdef BITS_BIG_ENDIAN ! 846: shift = - shift; ! 847: #endif ! 848: newpos = INTVAL (XEXP (x, 2)) + shift; ! 849: if (newpos >= 0 && ! 850: newpos < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (from))) ! 851: { ! 852: if (!undobuf.storage) ! 853: undobuf.storage = (char *) oballoc (0); ! 854: return gen_rtx (ZERO_EXTRACT, GET_MODE (x), ! 855: XEXP (to, 0), const1_rtx, ! 856: gen_rtx (CONST_INT, VOIDmode, newpos)); ! 857: } ! 858: } ! 859: break; ! 860: ! 861: case LSHIFTRT: ! 862: case ASHIFTRT: ! 863: case ROTATE: ! 864: case ROTATERT: ! 865: #ifdef SHIFT_COUNT_TRUNCATED ! 866: /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines). ! 867: True for all kinds of shifts and also for zero_extend. */ ! 868: if (XEXP (x, 1) == from ! 869: && (GET_CODE (to) == SIGN_EXTEND ! 870: || GET_CODE (to) == ZERO_EXTEND)) ! 871: { ! 872: if (!undobuf.storage) ! 873: undobuf.storage = (char *) oballoc (0); ! 874: this_to = gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0); ! 875: } ! 876: #endif ! 877: /* Two shifts in a row of same kind ! 878: in same direction with constant counts ! 879: may be combined. */ ! 880: if (XEXP (x, 0) == from ! 881: && GET_CODE (to) == GET_CODE (x) ! 882: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 883: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 884: && INTVAL (XEXP (to, 1)) > 0 ! 885: && INTVAL (XEXP (x, 1)) > 0 ! 886: && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1)) ! 887: < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (x)))) ! 888: { ! 889: if (!undobuf.storage) ! 890: undobuf.storage = (char *) oballoc (0); ! 891: return gen_rtx (GET_CODE (x), GET_MODE (x), ! 892: XEXP (to, 0), ! 893: gen_rtx (CONST_INT, VOIDmode, ! 894: INTVAL (XEXP (x, 1)) ! 895: + INTVAL (XEXP (to, 1)))); ! 896: } ! 897: break; ! 898: ! 899: case LSHIFT: ! 900: case ASHIFT: ! 901: #ifdef SHIFT_COUNT_TRUNCATED ! 902: /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines). ! 903: True for all kinds of shifts and also for zero_extend. */ ! 904: if (XEXP (x, 1) == from ! 905: && (GET_CODE (to) == SIGN_EXTEND ! 906: || GET_CODE (to) == ZERO_EXTEND)) ! 907: { ! 908: if (!undobuf.storage) ! 909: undobuf.storage = (char *) oballoc (0); ! 910: this_to = gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0); ! 911: } ! 912: #endif ! 913: /* (lshift (and (lshiftrt <foo> <X>) <Y>) <X>) ! 914: happens copying between bit fields in similar structures. ! 915: It can be replaced by one and instruction. ! 916: It does not matter whether the shifts are logical or arithmetic. */ ! 917: if (GET_CODE (XEXP (x, 0)) == AND ! 918: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 919: && INTVAL (XEXP (x, 1)) > 0 ! 920: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! 921: && XEXP (XEXP (x, 0), 0) == from ! 922: && (GET_CODE (to) == LSHIFTRT ! 923: || GET_CODE (to) == ASHIFTRT) ! 924: #if 0 ! 925: /* I now believe this restriction is unnecessary. ! 926: The outer shift will discard those bits in any case, right? */ ! 927: ! 928: /* If inner shift is arithmetic, either it shifts left or ! 929: the bits it shifts the sign into are zeroed by the and. */ ! 930: && (INTVAL (XEXP (x, 1)) < 0 ! 931: || ((unsigned) INTVAL (XEXP (XEXP (x, 0), 1)) ! 932: < 1 << (GET_MODE_BITSIZE (GET_MODE (x)) ! 933: - INTVAL (XEXP (x, 0))))) ! 934: #endif ! 935: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 936: && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1))) ! 937: { ! 938: if (!undobuf.storage) ! 939: undobuf.storage = (char *) oballoc (0); ! 940: /* The constant in the new `and' is <Y> << <X> ! 941: but clear out all bits that don't belong in our mode. */ ! 942: return gen_rtx (AND, GET_MODE (x), XEXP (to, 0), ! 943: gen_rtx (CONST_INT, VOIDmode, ! 944: (GET_MODE_MASK (GET_MODE (x)) ! 945: & ((GET_MODE_MASK (GET_MODE (x)) ! 946: & INTVAL (XEXP (XEXP (x, 0), 1))) ! 947: << INTVAL (XEXP (x, 1)))))); ! 948: } ! 949: /* Two shifts in a row in same direction with constant counts ! 950: may be combined. */ ! 951: if (XEXP (x, 0) == from ! 952: && (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT) ! 953: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 954: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 955: && INTVAL (XEXP (to, 1)) > 0 ! 956: && INTVAL (XEXP (x, 1)) > 0 ! 957: && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1)) ! 958: < BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (x)))) ! 959: { ! 960: if (!undobuf.storage) ! 961: undobuf.storage = (char *) oballoc (0); ! 962: return gen_rtx (GET_CODE (x), GET_MODE (x), ! 963: XEXP (to, 0), ! 964: gen_rtx (CONST_INT, VOIDmode, ! 965: INTVAL (XEXP (x, 1)) ! 966: + INTVAL (XEXP (to, 1)))); ! 967: } ! 968: /* (ashift (ashiftrt <foo> <X>) <X>) ! 969: (or, on some machines, (ashift (ashift <foo> <-X>) <X>) instead) ! 970: happens if you divide by 2**N and then multiply by 2**N. ! 971: It can be replaced by one `and' instruction. ! 972: It does not matter whether the shifts are logical or arithmetic. */ ! 973: if (GET_CODE (XEXP (x, 1)) == CONST_INT ! 974: && INTVAL (XEXP (x, 1)) > 0 ! 975: && XEXP (x, 0) == from ! 976: && (((GET_CODE (to) == LSHIFTRT || GET_CODE (to) == ASHIFTRT) ! 977: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 978: && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1))) ! 979: || ! 980: ((GET_CODE (to) == LSHIFT || GET_CODE (to) == ASHIFT) ! 981: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 982: && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (to, 1))))) ! 983: { ! 984: if (!undobuf.storage) ! 985: undobuf.storage = (char *) oballoc (0); ! 986: /* The constant in the new `and' is <Y> << <X> ! 987: but clear out all bits that don't belong in our mode. */ ! 988: return gen_rtx (AND, GET_MODE (x), XEXP (to, 0), ! 989: gen_rtx (CONST_INT, VOIDmode, ! 990: (GET_MODE_MASK (GET_MODE (x)) ! 991: & (GET_MODE_MASK (GET_MODE (x)) ! 992: << INTVAL (XEXP (x, 1)))))); ! 993: } ! 994: ! 995: } ! 996: ! 997: len = GET_RTX_LENGTH (code); ! 998: fmt = GET_RTX_FORMAT (code); ! 999: ! 1000: /* Don't replace FROM where it is being stored in rather than used. */ ! 1001: if (code == SET && SET_DEST (x) == from) ! 1002: fmt = "ie"; ! 1003: ! 1004: for (i = 0; i < len; i++) ! 1005: { ! 1006: if (fmt[i] == 'E') ! 1007: { ! 1008: register int j; ! 1009: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 1010: { ! 1011: register rtx new; ! 1012: if (XVECEXP (x, i, j) == from) ! 1013: new = this_to; ! 1014: else ! 1015: new = subst (XVECEXP (x, i, j), from, to); ! 1016: if (new != XVECEXP (x, i, j)) ! 1017: { ! 1018: if (undobuf.num_undo < MAX_UNDO) ! 1019: { ! 1020: undobuf.undo[undobuf.num_undo].where = &XVECEXP (x, i, j); ! 1021: undobuf.undo[undobuf.num_undo].old_contents = XVECEXP (x, i, j); ! 1022: XVECEXP (x, i, j) = new; ! 1023: } ! 1024: undobuf.num_undo++; ! 1025: } ! 1026: } ! 1027: } ! 1028: else if (fmt[i] == 'e') ! 1029: { ! 1030: register rtx new; ! 1031: ! 1032: if (XEXP (x, i) == from) ! 1033: new = this_to; ! 1034: else ! 1035: new = subst (XEXP (x, i), from, to); ! 1036: ! 1037: if (new != XEXP (x, i)) ! 1038: { ! 1039: if (undobuf.num_undo < MAX_UNDO) ! 1040: { ! 1041: undobuf.undo[undobuf.num_undo].where = &XEXP (x, i); ! 1042: undobuf.undo[undobuf.num_undo].old_contents = XEXP (x, i); ! 1043: XEXP (x, i) = new; ! 1044: } ! 1045: undobuf.num_undo++; ! 1046: } ! 1047: } ! 1048: } ! 1049: return x; ! 1050: } ! 1051: ! 1052: /* This is the AND case of the function subst. */ ! 1053: ! 1054: static rtx ! 1055: simplify_and_const_int (x, from, to) ! 1056: rtx x, from, to; ! 1057: { ! 1058: register rtx varop = XEXP (x, 0); ! 1059: register int constop = INTVAL (XEXP (x, 1)); ! 1060: ! 1061: /* (and (subreg (and <foo> <constant>) 0) <constant>) ! 1062: results from an andsi followed by an andqi, ! 1063: which happens frequently when storing bit-fields ! 1064: on something whose result comes from an andsi. */ ! 1065: if (GET_CODE (varop) == SUBREG ! 1066: && XEXP (varop, 0) == from ! 1067: && subreg_lowpart_p (varop) ! 1068: && GET_CODE (to) == AND ! 1069: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1070: /* Verify that the result of the outer `and' ! 1071: is not affected by any bits not defined in the inner `and'. ! 1072: True if the outer mode is narrower, or if the outer constant ! 1073: masks to zero all the bits that the inner mode doesn't have. */ ! 1074: && (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (from)) ! 1075: || constop & (-1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (from)))) == 0)) ! 1076: { ! 1077: if (!undobuf.storage) ! 1078: undobuf.storage = (char *) oballoc (0); ! 1079: return gen_rtx (AND, GET_MODE (x), ! 1080: gen_lowpart (GET_MODE (x), XEXP (to, 0)), ! 1081: gen_rtx (CONST_INT, VOIDmode, ! 1082: constop ! 1083: /* Remember that the bits outside that mode ! 1084: are not being changed, so the effect ! 1085: is as if they were all 1. */ ! 1086: & INTVAL (XEXP (to, 1)))); ! 1087: } ! 1088: /* (and (zero_extend <foo>) <constant>) ! 1089: often results from storing in a bit-field something ! 1090: that was calculated as a short. Replace with a single `and' ! 1091: in whose constant all bits not in <foo>'s mode are zero. */ ! 1092: if (varop == from ! 1093: && GET_CODE (to) == ZERO_EXTEND) ! 1094: { ! 1095: if (!undobuf.storage) ! 1096: undobuf.storage = (char *) oballoc (0); ! 1097: return gen_rtx (AND, GET_MODE (x), ! 1098: gen_rtx (SUBREG, GET_MODE (x), ! 1099: XEXP (to, 0), 0), ! 1100: gen_rtx (CONST_INT, VOIDmode, ! 1101: constop ! 1102: & ((1 << (BITS_PER_UNIT * GET_MODE_SIZE (GET_MODE (XEXP (to, 0))))) - 1))); ! 1103: } ! 1104: /* (and (sign_extend <foo>) <constant>) ! 1105: can be replaced with (and (subreg <foo>) <constant>) ! 1106: if <constant> is narrower than <foo>'s mode, ! 1107: or with (zero_extend <foo>) if <constant> is a mask for that mode. */ ! 1108: if (varop == from ! 1109: && GET_CODE (to) == SIGN_EXTEND ! 1110: && ((unsigned) constop ! 1111: <= ((1 << (BITS_PER_UNIT ! 1112: * GET_MODE_SIZE (GET_MODE (XEXP (to, 0))))) ! 1113: - 1))) ! 1114: { ! 1115: if (!undobuf.storage) ! 1116: undobuf.storage = (char *) oballoc (0); ! 1117: if (constop == ((1 << (BITS_PER_UNIT ! 1118: * GET_MODE_SIZE (GET_MODE (XEXP (to, 0))))) ! 1119: - 1)) ! 1120: return gen_rtx (ZERO_EXTEND, GET_MODE (x), XEXP (to, 0)); ! 1121: return gen_rtx (AND, GET_MODE (x), ! 1122: gen_rtx (SUBREG, GET_MODE (x), ! 1123: XEXP (to, 0), 0), ! 1124: XEXP (x, 1)); ! 1125: } ! 1126: /* (and (and <foo> <constant>) <constant>) ! 1127: comes from two and instructions in a row. */ ! 1128: if (varop == from ! 1129: && GET_CODE (to) == AND ! 1130: && GET_CODE (XEXP (to, 1)) == CONST_INT) ! 1131: { ! 1132: if (!undobuf.storage) ! 1133: undobuf.storage = (char *) oballoc (0); ! 1134: return gen_rtx (AND, GET_MODE (x), ! 1135: XEXP (to, 0), ! 1136: gen_rtx (CONST_INT, VOIDmode, ! 1137: constop ! 1138: & INTVAL (XEXP (to, 1)))); ! 1139: } ! 1140: /* (and (ashiftrt (ashift FOO N) N) CONST) ! 1141: may be simplified to (and FOO CONST) if CONST masks off the bits ! 1142: changed by the two shifts. */ ! 1143: if (GET_CODE (varop) == ASHIFTRT ! 1144: && GET_CODE (XEXP (varop, 1)) == CONST_INT ! 1145: && XEXP (varop, 0) == from ! 1146: && GET_CODE (to) == ASHIFT ! 1147: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1148: && INTVAL (XEXP (varop, 1)) == INTVAL (XEXP (to, 1)) ! 1149: && ((unsigned) constop >> INTVAL (XEXP (varop, 1))) == 0) ! 1150: { ! 1151: if (!undobuf.storage) ! 1152: undobuf.storage = (char *) oballoc (0); ! 1153: /* If CONST is a mask for the low byte, ! 1154: change this into a zero-extend instruction ! 1155: from just the low byte of FOO. */ ! 1156: if (constop == (1 << BITS_PER_UNIT) - 1) ! 1157: { ! 1158: rtx temp = gen_lowpart_for_combine (QImode, XEXP (to, 0)); ! 1159: if (temp) ! 1160: return gen_rtx (ZERO_EXTEND, GET_MODE (x), temp); ! 1161: } ! 1162: return gen_rtx (AND, GET_MODE (x), ! 1163: XEXP (to, 0), XEXP (x, 1)); ! 1164: } ! 1165: ! 1166: /* No simplification applies. */ ! 1167: return 0; ! 1168: } ! 1169: ! 1170: /* Like gen_lowpart but for use by combine. In combine it is not possible ! 1171: to create any new pseudoregs. However, it is safe to create ! 1172: invalid memory addresses, because combine will try to recognize ! 1173: them and all they will do is make the combine attempt fail. ! 1174: ! 1175: Also, return zero if we don't see a way to make a lowpart. */ ! 1176: ! 1177: static rtx ! 1178: gen_lowpart_for_combine (mode, x) ! 1179: enum machine_mode mode; ! 1180: register rtx x; ! 1181: { ! 1182: if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG) ! 1183: return gen_lowpart (mode, x); ! 1184: if (GET_MODE (x) == mode) ! 1185: return 0; ! 1186: if (GET_CODE (x) == VOLATILE) ! 1187: return 0; ! 1188: if (GET_CODE (x) == MEM) ! 1189: { ! 1190: register int offset = 0; ! 1191: #ifdef WORDS_BIG_ENDIAN ! 1192: offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) ! 1193: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD)); ! 1194: #endif ! 1195: #ifdef BYTES_BIG_ENDIAN ! 1196: if (GET_MODE_SIZE (mode) < UNITS_PER_WORD) ! 1197: offset -= (GET_MODE_SIZE (mode) ! 1198: - min (UNITS_PER_WORD, ! 1199: GET_MODE_SIZE (GET_MODE (x)))); ! 1200: #endif ! 1201: return gen_rtx (MEM, mode, plus_constant (XEXP (x, 0), ! 1202: offset)); ! 1203: } ! 1204: else ! 1205: return 0; ! 1206: } ! 1207: ! 1208: /* After substitution, if the resulting pattern looks like ! 1209: (set (cc0) (and ...)), this function is called to simplify the ! 1210: pattern into a bit-field operation if possible. */ ! 1211: ! 1212: static void ! 1213: simplify_set_cc0_and (insn) ! 1214: rtx insn; ! 1215: { ! 1216: register rtx value = XEXP (PATTERN (insn), 1); ! 1217: register rtx op0 = XEXP (value, 0); ! 1218: register rtx op1 = XEXP (value, 1); ! 1219: int offset = 0; ! 1220: rtx var = 0; ! 1221: rtx bitnum = 0; ! 1222: int temp; ! 1223: int unit; ! 1224: ! 1225: /* Look for a constant power of 2 or a shifted 1 ! 1226: on either side of the AND. Set VAR to the other side. ! 1227: Set BITNUM to the shift count of the 1 (as an rtx). ! 1228: Or, if bit number is constant, set OFFSET to the bit number. */ ! 1229: ! 1230: switch (GET_CODE (op0)) ! 1231: { ! 1232: case CONST_INT: ! 1233: temp = exact_log2 (INTVAL (op0)); ! 1234: if (temp < 0) ! 1235: return; ! 1236: offset = temp; ! 1237: var = op1; ! 1238: break; ! 1239: ! 1240: case ASHIFT: ! 1241: case LSHIFT: ! 1242: if (XEXP (op0, 0) == const1_rtx) ! 1243: { ! 1244: bitnum = XEXP (op0, 1); ! 1245: var = op1; ! 1246: } ! 1247: } ! 1248: if (var == 0) ! 1249: switch (GET_CODE (op1)) ! 1250: { ! 1251: case CONST_INT: ! 1252: temp = exact_log2 (INTVAL (op1)); ! 1253: if (temp < 0) ! 1254: return; ! 1255: offset = temp; ! 1256: var = op0; ! 1257: break; ! 1258: ! 1259: case ASHIFT: ! 1260: case LSHIFT: ! 1261: if (XEXP (op1, 0) == const1_rtx) ! 1262: { ! 1263: bitnum = XEXP (op1, 1); ! 1264: var = op0; ! 1265: } ! 1266: } ! 1267: ! 1268: /* If VAR is 0, we didn't find something recognizable. */ ! 1269: if (var == 0) ! 1270: return; ! 1271: ! 1272: if (!undobuf.storage) ! 1273: undobuf.storage = (char *) oballoc (0); ! 1274: ! 1275: /* If the bit position is currently exactly 0, ! 1276: extract a right-shift from the variable portion. */ ! 1277: if (offset == 0 ! 1278: && (GET_CODE (var) == ASHIFTRT || GET_CODE (var) == LSHIFTRT)) ! 1279: { ! 1280: bitnum = XEXP (var, 1); ! 1281: var = XEXP (var, 0); ! 1282: } ! 1283: ! 1284: #ifdef BITS_BIG_ENDIAN ! 1285: unit = GET_MODE_SIZE (GET_MODE (var)) * BITS_PER_UNIT - 1; ! 1286: ! 1287: if (bitnum != 0) ! 1288: bitnum = gen_rtx (MINUS, SImode, ! 1289: gen_rtx (CONST_INT, VOIDmode, unit), bitnum); ! 1290: else ! 1291: offset = unit - offset; ! 1292: #endif ! 1293: ! 1294: if (bitnum == 0) ! 1295: bitnum = gen_rtx (CONST_INT, VOIDmode, offset); ! 1296: ! 1297: if (GET_CODE (var) == SUBREG && SUBREG_WORD (var) == 0) ! 1298: var = SUBREG_REG (var); ! 1299: ! 1300: if (undobuf.num_undo < MAX_UNDO) ! 1301: { ! 1302: undobuf.undo[undobuf.num_undo].where = &XEXP (PATTERN (insn), 1); ! 1303: undobuf.undo[undobuf.num_undo].old_contents = value; ! 1304: XEXP (PATTERN (insn), 1) ! 1305: = gen_rtx (ZERO_EXTRACT, VOIDmode, var, const1_rtx, bitnum); ! 1306: } ! 1307: undobuf.num_undo++; ! 1308: } ! 1309: ! 1310: /* Update the records of when each REG was most recently set or killed ! 1311: for the things done by INSN. This is the last thing done in processing ! 1312: INSN in the combiner loop. ! 1313: ! 1314: We update reg_last_set, reg_last_death, and also the similar information ! 1315: mem_last_set (which insn most recently modified memory) ! 1316: and last_call_cuid (which insn was the most recent subroutine call). */ ! 1317: ! 1318: static void ! 1319: record_dead_and_set_regs (insn) ! 1320: rtx insn; ! 1321: { ! 1322: register rtx link; ! 1323: for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) ! 1324: { ! 1325: if ((enum reg_note) GET_MODE (link) == REG_DEAD) ! 1326: reg_last_death[REGNO (XEXP (link, 0))] = insn; ! 1327: else if ((enum reg_note) GET_MODE (link) == REG_INC) ! 1328: reg_last_set[REGNO (XEXP (link, 0))] = insn; ! 1329: } ! 1330: ! 1331: if (GET_CODE (insn) == CALL_INSN) ! 1332: last_call_cuid = mem_last_set = INSN_CUID (insn); ! 1333: ! 1334: if (GET_CODE (PATTERN (insn)) == PARALLEL) ! 1335: { ! 1336: register int i; ! 1337: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) ! 1338: { ! 1339: register rtx elt = XVECEXP (PATTERN (insn), 0, i); ! 1340: register enum rtx_code code = GET_CODE (elt); ! 1341: if (code == SET || code == CLOBBER) ! 1342: { ! 1343: if (GET_CODE (XEXP (elt, 0)) == REG) ! 1344: reg_last_set[REGNO (XEXP (elt, 0))] = insn; ! 1345: else if (GET_CODE (XEXP (elt, 0)) == MEM) ! 1346: mem_last_set = INSN_CUID (insn); ! 1347: } ! 1348: } ! 1349: } ! 1350: else if (GET_CODE (PATTERN (insn)) == SET ! 1351: || GET_CODE (PATTERN (insn)) == CLOBBER) ! 1352: { ! 1353: register rtx x = XEXP (PATTERN (insn), 0); ! 1354: if (GET_CODE (x) == REG) ! 1355: reg_last_set[REGNO (x)] = insn; ! 1356: else if (GET_CODE (x) == MEM) ! 1357: mem_last_set = INSN_CUID (insn); ! 1358: } ! 1359: } ! 1360: ! 1361: /* Return nonzero if expression X refers to a REG or to memory ! 1362: that is set in an instruction more recent than FROM_CUID. */ ! 1363: ! 1364: static int ! 1365: use_crosses_set_p (x, from_cuid) ! 1366: register rtx x; ! 1367: int from_cuid; ! 1368: { ! 1369: register char *fmt; ! 1370: register int i; ! 1371: register enum rtx_code code = GET_CODE (x); ! 1372: ! 1373: if (code == REG) ! 1374: { ! 1375: register int regno = REGNO (x); ! 1376: return (reg_last_set[regno] ! 1377: && INSN_CUID (reg_last_set[regno]) > from_cuid); ! 1378: } ! 1379: ! 1380: if (code == MEM && mem_last_set > from_cuid) ! 1381: return 1; ! 1382: ! 1383: fmt = GET_RTX_FORMAT (code); ! 1384: ! 1385: for (i = GET_RTX_LENGTH (code); i >= 0; i--) ! 1386: { ! 1387: if (fmt[i] == 'E') ! 1388: { ! 1389: register int j; ! 1390: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 1391: if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid)) ! 1392: return 1; ! 1393: } ! 1394: else if (fmt[i] == 'e' ! 1395: && use_crosses_set_p (XEXP (x, i), from_cuid)) ! 1396: return 1; ! 1397: } ! 1398: return 0; ! 1399: } ! 1400: ! 1401: /* Return nonzero if reg REGNO is marked as dying in INSN. */ ! 1402: ! 1403: int ! 1404: regno_dead_p (regno, insn) ! 1405: int regno; ! 1406: rtx insn; ! 1407: { ! 1408: register rtx link; ! 1409: ! 1410: for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) ! 1411: if (REGNO (XEXP (link, 0)) == regno ! 1412: && ((enum reg_note) GET_MODE (link) == REG_DEAD ! 1413: || (enum reg_note) GET_MODE (link) == REG_INC)) ! 1414: return 1; ! 1415: ! 1416: return 0; ! 1417: } ! 1418: ! 1419: /* Remove register number REGNO from the dead registers list of INSN. */ ! 1420: ! 1421: static void ! 1422: remove_death (regno, insn) ! 1423: int regno; ! 1424: rtx insn; ! 1425: { ! 1426: register rtx link, next; ! 1427: while ((link = REG_NOTES (insn)) ! 1428: && REGNO (XEXP (link, 0)) == regno ! 1429: && (enum reg_note) GET_MODE (link) == REG_DEAD) ! 1430: REG_NOTES (insn) = XEXP (link, 1); ! 1431: ! 1432: if (link) ! 1433: while (next = XEXP (link, 1)) ! 1434: { ! 1435: if (REGNO (XEXP (next, 0)) == regno ! 1436: && (enum reg_note) GET_MODE (next) == REG_DEAD) ! 1437: XEXP (link, 1) = XEXP (next, 1); ! 1438: else ! 1439: link = next; ! 1440: } ! 1441: } ! 1442: ! 1443: /* Return nonzero if J is the first insn following I, ! 1444: not counting labels, line numbers, etc. ! 1445: We assume that J follows I. */ ! 1446: ! 1447: static int ! 1448: adjacent_insns_p (i, j) ! 1449: rtx i, j; ! 1450: { ! 1451: register rtx insn; ! 1452: for (insn = NEXT_INSN (i); insn != j; insn = NEXT_INSN (insn)) ! 1453: if (GET_CODE (insn) == INSN ! 1454: || GET_CODE (insn) == CALL_INSN ! 1455: || GET_CODE (insn) == JUMP_INSN) ! 1456: return 0; ! 1457: return 1; ! 1458: } ! 1459: ! 1460: /* Concatenate the list of logical links LINKS ! 1461: into INSN's list of logical links. ! 1462: Modifies LINKS destructively. */ ! 1463: ! 1464: static void ! 1465: add_links (insn, links) ! 1466: rtx insn, links; ! 1467: { ! 1468: if (LOG_LINKS (insn) == 0) ! 1469: LOG_LINKS (insn) = links; ! 1470: else ! 1471: { ! 1472: register rtx next, prev = LOG_LINKS (insn); ! 1473: while (next = XEXP (prev, 1)) ! 1474: prev = next; ! 1475: XEXP (prev, 1) = links; ! 1476: } ! 1477: } ! 1478: ! 1479: /* Concatenate the any elements of the list of reg-notes INCS ! 1480: which are of type REG_INC ! 1481: into INSN's list of reg-notes. */ ! 1482: ! 1483: static void ! 1484: add_incs (insn, incs) ! 1485: rtx insn, incs; ! 1486: { ! 1487: register rtx tail; ! 1488: ! 1489: for (tail = incs; tail; tail = XEXP (tail, 1)) ! 1490: if ((enum reg_note) GET_MODE (tail) == REG_INC) ! 1491: REG_NOTES (insn) ! 1492: = gen_rtx (EXPR_LIST, REG_INC, XEXP (tail, 0), REG_NOTES (insn)); ! 1493: } ! 1494: ! 1495: /* For each register (hardware or pseudo) used within expression X, ! 1496: if its death is in an instruction with cuid ! 1497: between FROM_CUID (inclusive) and TO_INSN (exclusive), ! 1498: mark it as dead in TO_INSN instead. ! 1499: ! 1500: This is done when X is being merged by combination into TO_INSN. */ ! 1501: ! 1502: static void ! 1503: move_deaths (x, from_cuid, to_insn) ! 1504: rtx x; ! 1505: int from_cuid; ! 1506: rtx to_insn; ! 1507: { ! 1508: register char *fmt; ! 1509: register int len, i; ! 1510: register enum rtx_code code = GET_CODE (x); ! 1511: ! 1512: if (code == REG) ! 1513: { ! 1514: register rtx where_dead = reg_last_death[REGNO (x)]; ! 1515: ! 1516: if (where_dead && INSN_CUID (where_dead) >= from_cuid ! 1517: && INSN_CUID (where_dead) < INSN_CUID (to_insn)) ! 1518: { ! 1519: remove_death (REGNO (x), reg_last_death[REGNO (x)]); ! 1520: if (! dead_or_set_p (to_insn, x)) ! 1521: REG_NOTES (to_insn) ! 1522: = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn)); ! 1523: } ! 1524: return; ! 1525: } ! 1526: ! 1527: len = GET_RTX_LENGTH (code); ! 1528: fmt = GET_RTX_FORMAT (code); ! 1529: ! 1530: for (i = 0; i < len; i++) ! 1531: { ! 1532: if (fmt[i] == 'E') ! 1533: { ! 1534: register int j; ! 1535: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 1536: move_deaths (XVECEXP (x, i, j), from_cuid, to_insn); ! 1537: } ! 1538: else if (fmt[i] == 'e') ! 1539: move_deaths (XEXP (x, i), from_cuid, to_insn); ! 1540: } ! 1541: } ! 1542: ! 1543: dump_combine_stats (file) ! 1544: char *file; ! 1545: { ! 1546: fprintf ! 1547: (file, ! 1548: ";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n" ! 1549: , combine_attempts, combine_merges, combine_extras, combine_successes); ! 1550: } ! 1551: ! 1552: dump_combine_total_stats (file) ! 1553: char *file; ! 1554: { ! 1555: fprintf ! 1556: (file, ! 1557: "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n", ! 1558: total_attempts, total_merges, total_extras, total_successes); ! 1559: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.