|
|
1.1 ! root 1: /* Optimize by combining instructions for GNU compiler. ! 2: Copyright (C) 1987, 1988 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 "flags.h" ! 67: #include "regs.h" ! 68: #include "basic-block.h" ! 69: #include "insn-config.h" ! 70: #include "recog.h" ! 71: ! 72: #define max(A,B) ((A) > (B) ? (A) : (B)) ! 73: #define min(A,B) ((A) < (B) ? (A) : (B)) ! 74: ! 75: /* It is not safe to use ordinary gen_lowpart in combine. ! 76: Use gen_lowpart_for_combine instead. See comments there. */ ! 77: #define gen_lowpart dont_use_gen_lowpart_you_dummy ! 78: ! 79: /* Number of attempts to combine instructions in this function. */ ! 80: ! 81: static int combine_attempts; ! 82: ! 83: /* Number of attempts that got as far as substitution in this function. */ ! 84: ! 85: static int combine_merges; ! 86: ! 87: /* Number of instructions combined with added SETs in this function. */ ! 88: ! 89: static int combine_extras; ! 90: ! 91: /* Number of instructions combined in this function. */ ! 92: ! 93: static int combine_successes; ! 94: ! 95: /* Totals over entire compilation. */ ! 96: ! 97: static int total_attempts, total_merges, total_extras, total_successes; ! 98: ! 99: ! 100: /* Vector mapping INSN_UIDs to cuids. ! 101: The cuids are like uids but increase monononically always. ! 102: Combine always uses cuids so that it can compare them. ! 103: But actually renumbering the uids, which we used to do, ! 104: proves to be a bad idea because it makes it hard to compare ! 105: the dumps produced by earlier passes with those from later passes. */ ! 106: ! 107: static short *uid_cuid; ! 108: ! 109: /* Get the cuid of an insn. */ ! 110: ! 111: #define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)]) ! 112: ! 113: ! 114: /* Record last point of death of (hard or pseudo) register n. */ ! 115: ! 116: static rtx *reg_last_death; ! 117: ! 118: /* Record last point of modification of (hard or pseudo) register n. */ ! 119: ! 120: static rtx *reg_last_set; ! 121: ! 122: /* Record the cuid of the last insn that invalidated memory ! 123: (anything that writes memory, and subroutine calls). */ ! 124: ! 125: static int mem_last_set; ! 126: ! 127: /* Record the cuid of the last CALL_INSN ! 128: so we can tell whether a potential combination crosses any calls. */ ! 129: ! 130: static int last_call_cuid; ! 131: ! 132: /* When `subst' is called, this is the insn that is being modified ! 133: (by combining in a previous insn). The PATTERN of this insn ! 134: is still the old pattern partially modified and it should not be ! 135: looked at, but this may be used to examine the successors of the insn ! 136: to judge whether a simplification is valid. */ ! 137: ! 138: static rtx subst_insn; ! 139: ! 140: /* Record one modification to rtl structure ! 141: to be undone by storing old_contents into *where. */ ! 142: ! 143: struct undo ! 144: { ! 145: rtx *where; ! 146: rtx old_contents; ! 147: }; ! 148: ! 149: /* Record a bunch of changes to be undone, up to MAX_UNDO of them. ! 150: num_undo says how many are currently recorded. ! 151: storage is nonzero if we must undo the allocation of new storage. ! 152: The value of storage is what to pass to obfree. */ ! 153: ! 154: #define MAX_UNDO 10 ! 155: ! 156: struct undobuf ! 157: { ! 158: int num_undo; ! 159: char *storage; ! 160: struct undo undo[MAX_UNDO]; ! 161: }; ! 162: ! 163: static struct undobuf undobuf; ! 164: ! 165: /* Number of times the pseudo being substituted for ! 166: was found and replaced. */ ! 167: ! 168: static int n_occurrences; ! 169: ! 170: static void move_deaths (); ! 171: static void remove_death (); ! 172: static void record_dead_and_set_regs (); ! 173: int regno_dead_p (); ! 174: static int use_crosses_set_p (); ! 175: static rtx subst (); ! 176: static void undo_all (); ! 177: static void copy_substitutions (); ! 178: static void add_links (); ! 179: static void add_incs (); ! 180: static int insn_has_inc_p (); ! 181: static int adjacent_insns_p (); ! 182: static rtx simplify_and_const_int (); ! 183: static rtx gen_lowpart_for_combine (); ! 184: static void simplify_set_cc0_and (); ! 185: ! 186: /* Main entry point for combiner. F is the first insn of the function. ! 187: NREGS is the first unused pseudo-reg number. */ ! 188: ! 189: void ! 190: combine_instructions (f, nregs) ! 191: rtx f; ! 192: int nregs; ! 193: { ! 194: register rtx insn; ! 195: register int i; ! 196: register rtx links, nextlinks; ! 197: rtx prev; ! 198: ! 199: combine_attempts = 0; ! 200: combine_merges = 0; ! 201: combine_extras = 0; ! 202: combine_successes = 0; ! 203: ! 204: reg_last_death = (rtx *) alloca (nregs * sizeof (rtx)); ! 205: reg_last_set = (rtx *) alloca (nregs * sizeof (rtx)); ! 206: bzero (reg_last_death, nregs * sizeof (rtx)); ! 207: bzero (reg_last_set, nregs * sizeof (rtx)); ! 208: ! 209: init_recog (); ! 210: ! 211: /* Compute maximum uid value so uid_cuid can be allocated. */ ! 212: ! 213: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn)) ! 214: if (INSN_UID (insn) > i) ! 215: i = INSN_UID (insn); ! 216: ! 217: uid_cuid = (short *) alloca ((i + 1) * sizeof (short)); ! 218: ! 219: /* Compute the mapping from uids to cuids. ! 220: Cuids are numbers assigned to insns, like uids, ! 221: except that cuids increase monotonically through the code. */ ! 222: ! 223: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn)) ! 224: INSN_CUID (insn) = ++i; ! 225: ! 226: /* Now scan all the insns in forward order. */ ! 227: ! 228: last_call_cuid = 0; ! 229: mem_last_set = 0; ! 230: prev = 0; ! 231: ! 232: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 233: { ! 234: if (GET_CODE (insn) == INSN ! 235: || GET_CODE (insn) == CALL_INSN ! 236: || GET_CODE (insn) == JUMP_INSN) ! 237: { ! 238: retry: ! 239: /* Try this insn with each insn it links back to. */ ! 240: ! 241: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! 242: if (try_combine (insn, XEXP (links, 0), 0)) ! 243: goto retry; ! 244: ! 245: /* Try each sequence of three linked insns ending with this one. */ ! 246: ! 247: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! 248: if (GET_CODE (XEXP (links, 0)) != NOTE) ! 249: for (nextlinks = LOG_LINKS (XEXP (links, 0)); nextlinks; ! 250: nextlinks = XEXP (nextlinks, 1)) ! 251: if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0))) ! 252: goto retry; ! 253: ! 254: /* Try to combine a jump insn that uses CC0 ! 255: with a preceding insn that sets CC0, and maybe with its ! 256: logical predecessor as well. ! 257: This is how we make decrement-and-branch insns. ! 258: We need this special code because data flow connections ! 259: via CC0 do not get entered in LOG_LINKS. */ ! 260: ! 261: if (GET_CODE (insn) == JUMP_INSN ! 262: && prev != 0 ! 263: && GET_CODE (prev) == INSN ! 264: && GET_CODE (PATTERN (prev)) == SET ! 265: && GET_CODE (SET_DEST (PATTERN (prev))) == CC0) ! 266: { ! 267: if (try_combine (insn, prev, 0)) ! 268: goto retry; ! 269: ! 270: if (GET_CODE (prev) != NOTE) ! 271: for (nextlinks = LOG_LINKS (prev); nextlinks; ! 272: nextlinks = XEXP (nextlinks, 1)) ! 273: if (try_combine (insn, prev, XEXP (nextlinks, 0))) ! 274: goto retry; ! 275: } ! 276: #if 0 ! 277: /* Turned off because on 68020 it takes four insns to make ! 278: something like (a[b / 32] & (1 << (31 - (b % 32)))) != 0 ! 279: that could actually be optimized, and that's an unlikely piece of code. */ ! 280: /* If an insn gets or sets a bit field, try combining it ! 281: with two different insns whose results it uses. */ ! 282: if (GET_CODE (insn) == INSN ! 283: && GET_CODE (PATTERN (insn)) == SET ! 284: && (GET_CODE (SET_DEST (PATTERN (insn))) == ZERO_EXTRACT ! 285: || GET_CODE (SET_DEST (PATTERN (insn))) == SIGN_EXTRACT ! 286: || GET_CODE (SET_SRC (PATTERN (insn))) == ZERO_EXTRACT ! 287: || GET_CODE (SET_SRC (PATTERN (insn))) == SIGN_EXTRACT)) ! 288: { ! 289: for (links = LOG_LINKS (insn); links; links = XEXP (links, 1)) ! 290: if (GET_CODE (XEXP (links, 0)) != NOTE) ! 291: for (nextlinks = XEXP (links, 1); nextlinks; ! 292: nextlinks = XEXP (nextlinks, 1)) ! 293: if (try_combine (insn, XEXP (links, 0), XEXP (nextlinks, 0))) ! 294: goto retry; ! 295: } ! 296: #endif ! 297: record_dead_and_set_regs (insn); ! 298: prev = insn; ! 299: } ! 300: else if (GET_CODE (insn) != NOTE) ! 301: prev = 0; ! 302: } ! 303: total_attempts += combine_attempts; ! 304: total_merges += combine_merges; ! 305: total_extras += combine_extras; ! 306: total_successes += combine_successes; ! 307: } ! 308: ! 309: /* Try to combine the insns I1 and I2 into I3. ! 310: Here I1 appears earlier than I2, which is earlier than I3. ! 311: I1 can be zero; then we combine just I2 into I3. ! 312: ! 313: Return 1 if successful; if that happens, I1 and I2 are pseudo-deleted ! 314: by turning them into NOTEs, and I3 is modified. ! 315: Return 0 if the combination does not work. Then nothing is changed. */ ! 316: ! 317: static int ! 318: try_combine (i3, i2, i1) ! 319: register rtx i3, i2, i1; ! 320: { ! 321: register rtx newpat; ! 322: int added_sets_1 = 0; ! 323: int added_sets_2 = 0; ! 324: int total_sets; ! 325: int i2_is_used; ! 326: register rtx link; ! 327: int insn_code_number; ! 328: int recog_flags = 0; ! 329: rtx i2dest, i2src; ! 330: rtx i1dest, i1src; ! 331: int maxreg; ! 332: ! 333: combine_attempts++; ! 334: ! 335: /* Don't combine with something already used up by combination. */ ! 336: ! 337: if (GET_CODE (i2) == NOTE ! 338: || (i1 && GET_CODE (i1) == NOTE)) ! 339: return 0; ! 340: ! 341: /* Don't combine across a CALL_INSN, because that would possibly ! 342: change whether the life span of some REGs crosses calls or not, ! 343: and it is a pain to update that information. */ ! 344: ! 345: if (INSN_CUID (i2) < last_call_cuid ! 346: || (i1 && INSN_CUID (i1) < last_call_cuid)) ! 347: return 0; ! 348: ! 349: /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0. ! 350: That REG must be either set or dead by the final instruction ! 351: (so that we can safely forget about setting it). ! 352: Also test use_crosses_set_p to make sure that the value ! 353: that is to be substituted for the register ! 354: does not use any registers whose values alter in between. ! 355: Do not try combining with moves from one register to another ! 356: since it is better to let them be tied by register allocation. ! 357: (There is a switch to permit such combination; except the insns ! 358: that copy a function value into another register are never combined ! 359: because moving that too far away from the function call could cause ! 360: something else to be stored in that register in the interim.) ! 361: ! 362: A set of a SUBREG is considered as if it were a set from ! 363: SUBREG. Thus, (SET (SUBREG:X (REG:Y...)) (something:X...)) ! 364: is handled by substituting (SUBREG:Y (something:X...)) for (REG:Y...). */ ! 365: ! 366: if (GET_CODE (PATTERN (i2)) != SET) ! 367: return 0; ! 368: i2dest = SET_DEST (PATTERN (i2)); ! 369: i2src = SET_SRC (PATTERN (i2)); ! 370: if (GET_CODE (i2dest) == SUBREG) ! 371: { ! 372: i2dest = SUBREG_REG (i2dest); ! 373: i2src = gen_rtx (SUBREG, GET_MODE (i2dest), i2src, 0); ! 374: } ! 375: if (GET_CODE (i2dest) != CC0 ! 376: && (GET_CODE (i2dest) != REG ! 377: || (GET_CODE (i2src) == REG ! 378: && (!flag_combine_regs ! 379: || FUNCTION_VALUE_REGNO_P (REGNO (i2src)))) ! 380: || GET_CODE (i2src) == CALL ! 381: || use_crosses_set_p (i2src, INSN_CUID (i2)))) ! 382: return 0; ! 383: ! 384: if (i1 != 0) ! 385: { ! 386: if (GET_CODE (PATTERN (i1)) != SET) ! 387: return 0; ! 388: i1dest = SET_DEST (PATTERN (i1)); ! 389: i1src = SET_SRC (PATTERN (i1)); ! 390: if (GET_CODE (i1dest) == SUBREG) ! 391: { ! 392: i1dest = SUBREG_REG (i1dest); ! 393: i1src = gen_rtx (SUBREG, GET_MODE (i1dest), i1src, 0); ! 394: } ! 395: if (GET_CODE (i1dest) != CC0 ! 396: && (GET_CODE (i1dest) != REG ! 397: || (GET_CODE (i1src) == REG ! 398: && (!flag_combine_regs ! 399: || FUNCTION_VALUE_REGNO_P (REGNO (i1src)))) ! 400: || GET_CODE (i1src) == CALL ! 401: || use_crosses_set_p (i1src, INSN_CUID (i1)))) ! 402: return 0; ! 403: } ! 404: ! 405: /* If I1 or I2 contains an autoincrement or autodecrement, ! 406: make sure that register is not used between there and I3. ! 407: Also insist that I3 not be a jump; if it were one ! 408: and the incremented register were spilled, we would lose. */ ! 409: if ((link = find_reg_note (i2, REG_INC, 0)) != 0 ! 410: && (GET_CODE (i3) == JUMP_INSN ! 411: || reg_used_between_p (XEXP (link, 0), i2, i3) ! 412: || reg_mentioned_p (XEXP (link, 0), i3))) ! 413: return 0; ! 414: ! 415: if (i1 && (link = find_reg_note (i1, REG_INC, 0)) != 0 ! 416: && (GET_CODE (i3) == JUMP_INSN ! 417: || reg_used_between_p (XEXP (link, 0), i1, i3) ! 418: || reg_mentioned_p (XEXP (link, 0), i3))) ! 419: return 0; ! 420: ! 421: /* See if the SETs in i1 or i2 need to be kept around in the merged ! 422: instruction: whenever the value set there is still needed past i3. */ ! 423: added_sets_2 = (GET_CODE (i2dest) != CC0 ! 424: && ! dead_or_set_p (i3, i2dest)); ! 425: if (i1) ! 426: added_sets_1 = ! (dead_or_set_p (i3, i1dest) ! 427: || dead_or_set_p (i2, i1dest)); ! 428: ! 429: combine_merges++; ! 430: ! 431: undobuf.num_undo = 0; ! 432: undobuf.storage = 0; ! 433: ! 434: /* Substitute in the latest insn for the regs set by the earlier ones. */ ! 435: ! 436: maxreg = max_reg_num (); ! 437: ! 438: subst_insn = i3; ! 439: n_occurrences = 0; /* `subst' counts here */ ! 440: ! 441: newpat = subst (PATTERN (i3), i2dest, i2src); ! 442: /* Record whether i2's body now appears within i3's body. */ ! 443: i2_is_used = n_occurrences; ! 444: ! 445: if (i1) ! 446: { ! 447: n_occurrences = 0; ! 448: newpat = subst (newpat, i1dest, i1src); ! 449: } ! 450: ! 451: if (GET_CODE (PATTERN (i3)) == SET ! 452: && SET_DEST (PATTERN (i3)) == cc0_rtx ! 453: && (GET_CODE (SET_SRC (PATTERN (i3))) == AND ! 454: || GET_CODE (SET_SRC (PATTERN (i3))) == LSHIFTRT) ! 455: && next_insn_tests_no_inequality (i3)) ! 456: simplify_set_cc0_and (i3); ! 457: ! 458: if (max_reg_num () != maxreg) ! 459: abort (); ! 460: ! 461: /* If the actions of the earler insns must be kept ! 462: in addition to substituting them into the latest one, ! 463: we must make a new PARALLEL for the latest insn ! 464: to hold additional the SETs. */ ! 465: ! 466: if (added_sets_1 || added_sets_2) ! 467: { ! 468: combine_extras++; ! 469: ! 470: /* Arrange to free later what we allocate now ! 471: if we don't accept this combination. */ ! 472: if (!undobuf.storage) ! 473: undobuf.storage = (char *) oballoc (0); ! 474: ! 475: if (GET_CODE (newpat) == PARALLEL) ! 476: { ! 477: rtvec old = XVEC (newpat, 0); ! 478: total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2; ! 479: newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets)); ! 480: bcopy (&old->elem[0], &XVECEXP (newpat, 0, 0), ! 481: sizeof (old->elem[0]) * old->num_elem); ! 482: } ! 483: else ! 484: { ! 485: rtx old = newpat; ! 486: total_sets = 1 + added_sets_1 + added_sets_2; ! 487: newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets)); ! 488: XVECEXP (newpat, 0, 0) = old; ! 489: } ! 490: if (added_sets_1) ! 491: { ! 492: XVECEXP (newpat, 0, --total_sets) = PATTERN (i1); ! 493: } ! 494: if (added_sets_2) ! 495: { ! 496: /* If there is no I1, use I2's body as is. */ ! 497: if (i1 == 0 ! 498: /* If I2 was stuck into I3, then anything within it has ! 499: already had I1 substituted into it when that was done to I3. */ ! 500: || i2_is_used) ! 501: { ! 502: XVECEXP (newpat, 0, --total_sets) = PATTERN (i2); ! 503: } ! 504: else ! 505: XVECEXP (newpat, 0, --total_sets) ! 506: = subst (PATTERN (i2), i1dest, i1src); ! 507: } ! 508: } ! 509: ! 510: /* Fail if an autoincrement side-effect has been duplicated. */ ! 511: if ((i2_is_used > 1 && find_reg_note (i2, REG_INC, 0) != 0) ! 512: || (i1 != 0 && n_occurrences > 1 && find_reg_note (i1, REG_INC, 0) != 0)) ! 513: { ! 514: undo_all (); ! 515: return 0; ! 516: } ! 517: ! 518: /* Is the result of combination a valid instruction? */ ! 519: insn_code_number = recog (newpat, i3); ! 520: ! 521: if (insn_code_number >= 0) ! 522: { ! 523: /* Yes. Install it. */ ! 524: register int regno; ! 525: INSN_CODE (i3) = insn_code_number; ! 526: PATTERN (i3) = newpat; ! 527: /* If anything was substituted more than once, ! 528: copy it to avoid invalid shared rtl structure. */ ! 529: copy_substitutions (); ! 530: /* The data flowing into I2 now flows into I3. ! 531: But we cannot always move all of I2's LOG_LINKS into I3, ! 532: since they must go to a setting of a REG from the ! 533: first use following. If I2 was the first use following a set, ! 534: I3 is now a use, but it is not the first use ! 535: if some instruction between I2 and I3 is also a use. ! 536: Here, for simplicity, we move all the links only if ! 537: there are no real insns between I2 and I3. ! 538: Otherwise, we move only links that correspond to regs ! 539: that used to die in I2. They are always safe to move. */ ! 540: add_links (i3, i2, adjacent_insns_p (i2, i3)); ! 541: /* Most REGs that previously died in I2 now die in I3. */ ! 542: move_deaths (i2src, INSN_CUID (i2), i3); ! 543: if (GET_CODE (i2dest) == REG) ! 544: { ! 545: /* If the reg formerly set in I2 died only once and that was in I3, ! 546: zero its use count so it won't make `reload' do any work. */ ! 547: regno = REGNO (i2dest); ! 548: if (! added_sets_2) ! 549: { ! 550: reg_n_sets[regno]--; ! 551: /* Used to check && regno_dead_p (regno, i3) also here. */ ! 552: if (reg_n_sets[regno] == 0 ! 553: && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT] ! 554: & (1 << (regno % HOST_BITS_PER_INT)))) ! 555: reg_n_refs[regno] = 0; ! 556: } ! 557: /* If a ref to REGNO was substituted into I3 from I2, ! 558: then it still dies there if it previously did. ! 559: Otherwise either REGNO never did die in I3 so remove_death is safe ! 560: or this entire life of REGNO is gone so remove its death. */ ! 561: if (!added_sets_2 ! 562: && ! reg_mentioned_p (i2dest, PATTERN (i3))) ! 563: remove_death (regno, i3); ! 564: } ! 565: /* Any registers previously autoincremented in I2 ! 566: are now incremented in I3. */ ! 567: add_incs (i3, REG_NOTES (i2)); ! 568: if (i1) ! 569: { ! 570: /* Likewise, merge the info from I1 and get rid of it. */ ! 571: add_links (i3, i1, ! 572: adjacent_insns_p (i1, i2) && adjacent_insns_p (i2, i3)); ! 573: move_deaths (i1src, INSN_CUID (i1), i3); ! 574: if (GET_CODE (i1dest) == REG) ! 575: { ! 576: regno = REGNO (i1dest); ! 577: if (! added_sets_1) ! 578: { ! 579: reg_n_sets[regno]--; ! 580: /* Used to also check && regno_dead_p (regno, i3) here. */ ! 581: ! 582: if (reg_n_sets[regno] == 0 ! 583: && ! (basic_block_live_at_start[0][regno / HOST_BITS_PER_INT] ! 584: & (1 << (regno % HOST_BITS_PER_INT)))) ! 585: ! 586: reg_n_refs[regno] = 0; ! 587: } ! 588: /* If a ref to REGNO was substituted into I3 from I1, ! 589: then it still dies there if it previously did. ! 590: Else either REGNO never did die in I3 so remove_death is safe ! 591: or this entire life of REGNO is gone so remove its death. */ ! 592: if (! added_sets_1 ! 593: && ! reg_mentioned_p (i1dest, PATTERN (i3))) ! 594: remove_death (regno, i3); ! 595: } ! 596: add_incs (i3, REG_NOTES (i1)); ! 597: LOG_LINKS (i1) = 0; ! 598: PUT_CODE (i1, NOTE); ! 599: NOTE_LINE_NUMBER (i1) = NOTE_INSN_DELETED; ! 600: NOTE_SOURCE_FILE (i1) = 0; ! 601: } ! 602: /* Get rid of I2. */ ! 603: LOG_LINKS (i2) = 0; ! 604: PUT_CODE (i2, NOTE); ! 605: NOTE_LINE_NUMBER (i2) = NOTE_INSN_DELETED; ! 606: NOTE_SOURCE_FILE (i2) = 0; ! 607: ! 608: combine_successes++; ! 609: return 1; ! 610: } ! 611: ! 612: /* Failure: change I3 back the way it was. */ ! 613: undo_all (); ! 614: ! 615: return 0; ! 616: } ! 617: ! 618: /* Undo all the modifications recorded in undobuf. */ ! 619: ! 620: static void ! 621: undo_all () ! 622: { ! 623: register int i; ! 624: if (undobuf.num_undo > MAX_UNDO) ! 625: undobuf.num_undo = MAX_UNDO; ! 626: for (i = undobuf.num_undo - 1; i >= 0; i--) ! 627: *undobuf.undo[i].where = undobuf.undo[i].old_contents; ! 628: if (undobuf.storage) ! 629: obfree (undobuf.storage); ! 630: undobuf.num_undo = 0; ! 631: undobuf.storage = 0; ! 632: } ! 633: ! 634: /* If this insn had more than one substitution, ! 635: copy all but one, so that no invalid shared substructure is introduced. */ ! 636: ! 637: static void ! 638: copy_substitutions () ! 639: { ! 640: register int i; ! 641: if (undobuf.num_undo > 1) ! 642: { ! 643: for (i = undobuf.num_undo - 1; i >= 1; i--) ! 644: *undobuf.undo[i].where = copy_rtx (*undobuf.undo[i].where); ! 645: } ! 646: } ! 647: ! 648: /* Throughout X, replace FROM with TO, and return the result. ! 649: The result is TO if X is FROM; ! 650: otherwise the result is X, but its contents may have been modified. ! 651: If they were modified, a record was made in undobuf so that ! 652: undo_all will (among other things) return X to its original state. ! 653: ! 654: If the number of changes necessary is too much to record to undo, ! 655: the excess changes are not made, so the result is invalid. ! 656: The changes already made can still be undone. ! 657: undobuf.num_undo is incremented for such changes, so by testing that ! 658: the caller can tell whether the result is valid. ! 659: ! 660: `n_occurrences' is incremented each time FROM is replaced. */ ! 661: ! 662: static rtx ! 663: subst (x, from, to) ! 664: register rtx x, from, to; ! 665: { ! 666: register char *fmt; ! 667: register int len, i; ! 668: register enum rtx_code code; ! 669: char was_replaced[2]; ! 670: ! 671: #define SUBST(INTO, NEWVAL) \ ! 672: do { if (undobuf.num_undo < MAX_UNDO) \ ! 673: { \ ! 674: undobuf.undo[undobuf.num_undo].where = &INTO; \ ! 675: undobuf.undo[undobuf.num_undo].old_contents = INTO; \ ! 676: INTO = NEWVAL; \ ! 677: } \ ! 678: undobuf.num_undo++; } while (0) ! 679: ! 680: /* FAKE_EXTEND_SAFE_P (MODE, FROM) is 1 if (subreg:MODE FROM 0) is a safe ! 681: replacement for (zero_extend:MODE FROM) or (sign_extend:MODE FROM). ! 682: If it is 0, that cannot be done because it might cause a badly aligned ! 683: memory reference. */ ! 684: ! 685: /* Now we never do this for memory refs, because of the danger of ! 686: turning a reference to the last byte on a page into a page-crossing ! 687: reference that could get a spurious fault. It could be done safely ! 688: for certain cases but it's hard to check for them. */ ! 689: #if 0 ! 690: #define FAKE_EXTEND_SAFE_P(MODE, FROM) \ ! 691: (GET_CODE (FROM) == REG || \ ! 692: (GET_CODE (FROM) == MEM \ ! 693: && offsetable_address_p ((MODE), XEXP ((FROM), 0)) \ ! 694: && ! mode_dependent_address_p ((XEXP ((FROM), 0))))) ! 695: #else ! 696: #define FAKE_EXTEND_SAFE_P(MODE, FROM) (GET_CODE (FROM) == REG) ! 697: #endif ! 698: ! 699: if (x == from) ! 700: return to; ! 701: ! 702: /* It is possible to have a subexpression appear twice in the insn. ! 703: Suppose that FROM is a register that appears within TO. ! 704: Then, after that subexpression has been scanned once by `subst', ! 705: the second time it is scanned, TO may be found. If we were ! 706: to scan TO here, we would find FROM within it and create a ! 707: self-referent rtl structure which is completely wrong. */ ! 708: if (x == to) ! 709: return to; ! 710: ! 711: code = GET_CODE (x); ! 712: ! 713: /* A little bit of algebraic simplification here. */ ! 714: switch (code) ! 715: { ! 716: /* This case has no effect except to speed things up. */ ! 717: case REG: ! 718: case CONST_INT: ! 719: case CONST: ! 720: case SYMBOL_REF: ! 721: case LABEL_REF: ! 722: case PC: ! 723: case CC0: ! 724: return x; ! 725: } ! 726: ! 727: was_replaced[0] = 0; ! 728: was_replaced[1] = 0; ! 729: ! 730: len = GET_RTX_LENGTH (code); ! 731: fmt = GET_RTX_FORMAT (code); ! 732: ! 733: /* Don't replace FROM where it is being stored in rather than used. */ ! 734: if (code == SET && SET_DEST (x) == from) ! 735: fmt = "ie"; ! 736: if (code == SET && GET_CODE (SET_DEST (x)) == SUBREG ! 737: && SUBREG_REG (SET_DEST (x)) == from) ! 738: fmt = "ie"; ! 739: ! 740: for (i = 0; i < len; i++) ! 741: { ! 742: if (fmt[i] == 'E') ! 743: { ! 744: register int j; ! 745: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 746: { ! 747: register rtx new; ! 748: if (XVECEXP (x, i, j) == from) ! 749: new = to, n_occurrences++; ! 750: else ! 751: new = subst (XVECEXP (x, i, j), from, to); ! 752: if (new != XVECEXP (x, i, j)) ! 753: SUBST (XVECEXP (x, i, j), new); ! 754: } ! 755: } ! 756: else if (fmt[i] == 'e') ! 757: { ! 758: register rtx new; ! 759: ! 760: if (XEXP (x, i) == from) ! 761: { ! 762: new = to; ! 763: n_occurrences++; ! 764: if (i < 2) ! 765: was_replaced[i] = 1; ! 766: } ! 767: else ! 768: new = subst (XEXP (x, i), from, to); ! 769: ! 770: if (new != XEXP (x, i)) ! 771: SUBST (XEXP (x, i), new); ! 772: } ! 773: } ! 774: ! 775: /* A little bit of algebraic simplification here. */ ! 776: switch (code) ! 777: { ! 778: case SUBREG: ! 779: /* Changing mode twice with SUBREG => just change it once, ! 780: or not at all if changing back to starting mode. */ ! 781: if (SUBREG_REG (x) == to ! 782: && GET_CODE (to) == SUBREG ! 783: && SUBREG_WORD (x) == 0 ! 784: && SUBREG_WORD (to) == 0) ! 785: { ! 786: if (GET_MODE (x) == GET_MODE (SUBREG_REG (to))) ! 787: return SUBREG_REG (to); ! 788: SUBST (SUBREG_REG (x), SUBREG_REG (to)); ! 789: } ! 790: break; ! 791: ! 792: case NOT: ! 793: case NEG: ! 794: /* Don't let substitution introduce double-negatives. */ ! 795: if (was_replaced[0] ! 796: && GET_CODE (to) == code) ! 797: return XEXP (to, 0); ! 798: break; ! 799: ! 800: case FLOAT_TRUNCATE: ! 801: /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF. */ ! 802: if (was_replaced[0] ! 803: && GET_CODE (to) == FLOAT_EXTEND ! 804: && GET_MODE (XEXP (to, 0)) == GET_MODE (x)) ! 805: return XEXP (to, 0); ! 806: break; ! 807: ! 808: case PLUS: ! 809: /* In (plus <foo> (ashift <bar> <n>)) ! 810: change the shift to a multiply so we can recognize ! 811: scaled indexed addresses. */ ! 812: if ((was_replaced[0] ! 813: || was_replaced[1]) ! 814: && GET_CODE (to) == ASHIFT ! 815: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 816: && INTVAL (XEXP (to, 1)) < HOST_BITS_PER_INT) ! 817: { ! 818: rtx temp; ! 819: if (!undobuf.storage) ! 820: undobuf.storage = (char *) oballoc (0); ! 821: temp = gen_rtx (MULT, GET_MODE (to), ! 822: XEXP (to, 0), ! 823: gen_rtx (CONST_INT, VOIDmode, ! 824: 1 << INTVAL (XEXP (to, 1)))); ! 825: if (was_replaced[0]) ! 826: SUBST (XEXP (x, 0), temp); ! 827: else ! 828: SUBST (XEXP (x, 1), temp); ! 829: } ! 830: /* (plus X (neg Y)) becomes (minus X Y). */ ! 831: if (GET_CODE (XEXP (x, 1)) == NEG) ! 832: { ! 833: if (!undobuf.storage) ! 834: undobuf.storage = (char *) oballoc (0); ! 835: return gen_rtx (MINUS, GET_MODE (x), ! 836: XEXP (x, 0), XEXP (XEXP (x, 1), 0)); ! 837: } ! 838: /* (plus (neg X) Y) becomes (minus Y X). */ ! 839: if (GET_CODE (XEXP (x, 0)) == NEG) ! 840: { ! 841: if (!undobuf.storage) ! 842: undobuf.storage = (char *) oballoc (0); ! 843: return gen_rtx (MINUS, GET_MODE (x), ! 844: XEXP (x, 1), XEXP (XEXP (x, 0), 0)); ! 845: } ! 846: /* (plus (plus x c1) c2) => (plus x c1+c2) */ ! 847: if (GET_CODE (XEXP (x, 1)) == CONST_INT ! 848: && GET_CODE (XEXP (x, 0)) == PLUS ! 849: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT) ! 850: { ! 851: int sum = (INTVAL (XEXP (x, 1)) ! 852: + INTVAL (XEXP (XEXP (x, 0), 1))); ! 853: if (sum == 0) ! 854: return XEXP (XEXP (x, 0), 0); ! 855: if (!undobuf.storage) ! 856: undobuf.storage = (char *) oballoc (0); ! 857: SUBST (XEXP (x, 1), gen_rtx (CONST_INT, VOIDmode, sum)); ! 858: SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0)); ! 859: break; ! 860: } ! 861: /* If we have something (putative index) being added to a sum, ! 862: associate it so that any constant term is outermost. ! 863: That's because that's the way indexed addresses are ! 864: now supposed to appear. */ ! 865: if (((was_replaced[0] && GET_CODE (XEXP (x, 1)) == PLUS) ! 866: || (was_replaced[1] && GET_CODE (XEXP (x, 0)) == PLUS)) ! 867: || ! 868: ((was_replaced[0] || was_replaced[1]) ! 869: && GET_CODE (to) == PLUS)) ! 870: { ! 871: rtx offset = 0, base, index; ! 872: if (GET_CODE (to) != PLUS) ! 873: { ! 874: index = to; ! 875: base = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0); ! 876: } ! 877: else ! 878: { ! 879: index = was_replaced[0] ? XEXP (x, 1) : XEXP (x, 0); ! 880: base = to; ! 881: } ! 882: if (CONSTANT_ADDRESS_P (XEXP (base, 0))) ! 883: { ! 884: offset = XEXP (base, 0); ! 885: base = XEXP (base, 1); ! 886: } ! 887: else if (CONSTANT_ADDRESS_P (XEXP (base, 1))) ! 888: { ! 889: offset = XEXP (base, 1); ! 890: base = XEXP (base, 0); ! 891: } ! 892: if (offset != 0) ! 893: { ! 894: if (!undobuf.storage) ! 895: undobuf.storage = (char *) oballoc (0); ! 896: if (GET_CODE (offset) == CONST_INT) ! 897: return plus_constant (gen_rtx (PLUS, GET_MODE (index), ! 898: base, index), ! 899: INTVAL (offset)); ! 900: if (GET_CODE (index) == CONST_INT) ! 901: return plus_constant (gen_rtx (PLUS, GET_MODE (offset), ! 902: base, offset), ! 903: INTVAL (index)); ! 904: return gen_rtx (PLUS, GET_MODE (index), ! 905: gen_rtx (PLUS, GET_MODE (index), ! 906: base, index), ! 907: offset); ! 908: } ! 909: } ! 910: break; ! 911: ! 912: case MINUS: ! 913: /* Can simplify (minus:VOIDmode (zero/sign_extend FOO) CONST) ! 914: (which is a compare instruction, not a subtract instruction) ! 915: to (minus FOO CONST) if CONST fits in FOO's mode ! 916: and we are only testing equality. ! 917: In fact, this is valid for zero_extend if what follows is an ! 918: unsigned comparison, and for sign_extend with a signed comparison. */ ! 919: if (GET_MODE (x) == VOIDmode ! 920: && was_replaced[0] ! 921: && (GET_CODE (to) == ZERO_EXTEND || GET_CODE (to) == SIGN_EXTEND) ! 922: && next_insn_tests_no_inequality (subst_insn) ! 923: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 924: /* This is overly cautious by one bit, but saves worrying about ! 925: whether it is zero-extension or sign extension. */ ! 926: && ((unsigned) INTVAL (XEXP (x, 1)) ! 927: < (1 << (GET_MODE_BITSIZE (GET_MODE (XEXP (to, 0))) - 1)))) ! 928: SUBST (XEXP (x, 0), XEXP (to, 0)); ! 929: break; ! 930: ! 931: case EQ: ! 932: case NE: ! 933: /* If comparing a subreg against zero, discard the subreg. */ ! 934: if (was_replaced[0] ! 935: && GET_CODE (to) == SUBREG ! 936: && SUBREG_WORD (to) == 0 ! 937: && XEXP (x, 1) == const0_rtx) ! 938: SUBST (XEXP (x, 0), SUBREG_REG (to)); ! 939: ! 940: /* If comparing a ZERO_EXTRACT against zero, ! 941: canonicalize to a SIGN_EXTRACT, ! 942: since the two are equivalent here. */ ! 943: if (was_replaced[0] ! 944: && GET_CODE (to) == ZERO_EXTRACT ! 945: && XEXP (x, 1) == const0_rtx) ! 946: { ! 947: if (!undobuf.storage) ! 948: undobuf.storage = (char *) oballoc (0); ! 949: SUBST (XEXP (x, 0), ! 950: gen_rtx (SIGN_EXTRACT, GET_MODE (to), ! 951: XEXP (to, 0), XEXP (to, 1), ! 952: XEXP (to, 2))); ! 953: } ! 954: /* If we are putting (ASHIFT 1 x) into (EQ (AND ... y) 0), ! 955: arrange to return (EQ (SIGN_EXTRACT y 1 x) 0), ! 956: which is what jump-on-bit instructions are written with. */ ! 957: else if (XEXP (x, 1) == const0_rtx ! 958: && GET_CODE (XEXP (x, 0)) == AND ! 959: && (XEXP (XEXP (x, 0), 0) == to ! 960: || XEXP (XEXP (x, 0), 1) == to) ! 961: && GET_CODE (to) == ASHIFT ! 962: && XEXP (to, 0) == const1_rtx) ! 963: { ! 964: register rtx y = XEXP (XEXP (x, 0), ! 965: XEXP (XEXP (x, 0), 0) == to); ! 966: if (!undobuf.storage) ! 967: undobuf.storage = (char *) oballoc (0); ! 968: SUBST (XEXP (x, 0), ! 969: gen_rtx (SIGN_EXTRACT, GET_MODE (to), ! 970: y, ! 971: const1_rtx, XEXP (to, 1))); ! 972: } ! 973: ! 974: break; ! 975: ! 976: case ZERO_EXTEND: ! 977: if (was_replaced[0] ! 978: && GET_CODE (to) == ZERO_EXTEND) ! 979: SUBST (XEXP (x, 0), XEXP (to, 0)); ! 980: /* Zero-extending the result of an and with a constant can be done ! 981: with a wider and. */ ! 982: if (was_replaced[0] ! 983: && GET_CODE (to) == AND ! 984: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 985: && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)) ! 986: /* Avoid getting wrong result if the constant has high bits set ! 987: that are irrelevant in the narrow mode where it is being used. */ ! 988: && 0 == (INTVAL (XEXP (to, 1)) ! 989: & ~ GET_MODE_MASK (GET_MODE (to)))) ! 990: { ! 991: if (!undobuf.storage) ! 992: undobuf.storage = (char *) oballoc (0); ! 993: return gen_rtx (AND, GET_MODE (x), ! 994: gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), ! 995: XEXP (to, 1)); ! 996: } ! 997: /* Change (zero_extend:M (subreg:N (zero_extract:M ...) 0)) ! 998: to (zero_extract:M ...) if the field extracted fits in mode N. */ ! 999: if (GET_CODE (XEXP (x, 0)) == SUBREG ! 1000: && GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTRACT ! 1001: && GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)) == CONST_INT ! 1002: && (INTVAL (XEXP (XEXP (XEXP (x, 0), 0), 1)) ! 1003: <= GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))) ! 1004: { ! 1005: return XEXP (XEXP (x, 0), 0); ! 1006: } ! 1007: break; ! 1008: ! 1009: case SIGN_EXTEND: ! 1010: if (was_replaced[0] ! 1011: && GET_CODE (to) == SIGN_EXTEND) ! 1012: SUBST (XEXP (x, 0), XEXP (to, 0)); ! 1013: /* Sign-extending the result of an and with a constant can be done ! 1014: with a wider and, provided the high bit of the constant is 0. */ ! 1015: if (was_replaced[0] ! 1016: && GET_CODE (to) == AND ! 1017: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1018: && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0)) ! 1019: && ((INTVAL (XEXP (to, 1)) ! 1020: & (-1 << (GET_MODE_BITSIZE (GET_MODE (to)) - 1))) ! 1021: == 0)) ! 1022: { ! 1023: if (!undobuf.storage) ! 1024: undobuf.storage = (char *) oballoc (0); ! 1025: return gen_rtx (AND, GET_MODE (x), ! 1026: gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), ! 1027: XEXP (to, 1)); ! 1028: } ! 1029: break; ! 1030: ! 1031: case SET: ! 1032: /* In (set (zero-extract <x> <n> <y>) (and <foo> <(2**n-1) | anything>)) ! 1033: the `and' can be deleted. This can happen when storing a bit ! 1034: that came from a set-flag insn followed by masking to one bit. */ ! 1035: if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT ! 1036: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! 1037: && was_replaced[1] ! 1038: && GET_CODE (to) == AND ! 1039: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1040: && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1) ! 1041: & ~ INTVAL (XEXP (to, 1)))) ! 1042: { ! 1043: SUBST (XEXP (x, 1), XEXP (to, 0)); ! 1044: } ! 1045: /* In (set (zero-extract <x> <n> <y>) ! 1046: (subreg (and <foo> <(2**n-1) | anything>))) ! 1047: the `and' can be deleted. */ ! 1048: if (GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT ! 1049: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! 1050: && GET_CODE (XEXP (x, 1)) == SUBREG ! 1051: && SUBREG_WORD (XEXP (x, 1)) == 0 ! 1052: && GET_CODE (SUBREG_REG (XEXP (x, 1))) == AND ! 1053: && GET_CODE (XEXP (SUBREG_REG (XEXP (x, 1)), 1)) == CONST_INT ! 1054: && 0 == (((1 << INTVAL (XEXP (XEXP (x, 0), 1))) - 1) ! 1055: & ~ INTVAL (XEXP (SUBREG_REG (XEXP (x, 1)), 1)))) ! 1056: { ! 1057: SUBST (SUBREG_REG (XEXP (x, 1)), XEXP (SUBREG_REG (XEXP (x, 1)), 0)); ! 1058: } ! 1059: /* (set (zero_extract ...) (and/or/xor (zero_extract ...) const)), ! 1060: if both zero_extracts have the byte size and position, ! 1061: can be changed to avoid the byte extracts. */ ! 1062: if ((GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT ! 1063: || GET_CODE (XEXP (x, 0)) == SIGN_EXTRACT) ! 1064: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! 1065: && (GET_CODE (XEXP (x, 1)) == AND ! 1066: || GET_CODE (XEXP (x, 1)) == IOR ! 1067: || GET_CODE (XEXP (x, 1)) == XOR) ! 1068: && (GET_CODE (XEXP (XEXP (x, 1), 0)) == ZERO_EXTRACT ! 1069: || GET_CODE (XEXP (XEXP (x, 1), 0)) == SIGN_EXTRACT) ! 1070: && rtx_equal_p (XEXP (XEXP (XEXP (x, 1), 0), 1), ! 1071: XEXP (XEXP (x, 0), 1)) ! 1072: && rtx_equal_p (XEXP (XEXP (XEXP (x, 1), 0), 2), ! 1073: XEXP (XEXP (x, 0), 2)) ! 1074: && GET_CODE (XEXP (XEXP (x, 1), 0)) == GET_CODE (XEXP (x, 0)) ! 1075: && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT) ! 1076: { ! 1077: #ifdef BITS_BIG_ENDIAN ! 1078: int shiftcount ! 1079: = GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0))) ! 1080: - INTVAL (XEXP (XEXP (x, 0), 1)) - INTVAL (XEXP (XEXP (x, 0), 2)); ! 1081: #else ! 1082: int shiftcount ! 1083: = INTVAL (XEXP (XEXP (x, 0), 2)); ! 1084: #endif ! 1085: if (!undobuf.storage) ! 1086: undobuf.storage = (char *) oballoc (0); ! 1087: return ! 1088: gen_rtx (SET, VOIDmode, ! 1089: XEXP (XEXP (x, 0), 0), ! 1090: gen_rtx (GET_CODE (XEXP (x, 1)), ! 1091: GET_MODE (XEXP (XEXP (x, 0), 0)), ! 1092: XEXP (XEXP (XEXP (x, 1), 0), 0), ! 1093: gen_rtx (CONST_INT, VOIDmode, ! 1094: (INTVAL (XEXP (XEXP (x, 1), 1)) ! 1095: << shiftcount) ! 1096: + (GET_CODE (XEXP (x, 1)) == AND ! 1097: ? (1 << shiftcount) - 1 ! 1098: : 0)))); ! 1099: } ! 1100: break; ! 1101: ! 1102: case AND: ! 1103: if (GET_CODE (XEXP (x, 1)) == CONST_INT) ! 1104: { ! 1105: rtx tem = simplify_and_const_int (x, to); ! 1106: if (tem) ! 1107: return tem; ! 1108: } ! 1109: break; ! 1110: ! 1111: case FLOAT: ! 1112: /* (float (sign_extend <X>)) = (float <X>). */ ! 1113: if (was_replaced[0] ! 1114: && GET_CODE (to) == SIGN_EXTEND) ! 1115: SUBST (XEXP (x, 0), XEXP (to, 0)); ! 1116: break; ! 1117: ! 1118: case ZERO_EXTRACT: ! 1119: /* (ZERO_EXTRACT (TRUNCATE x)...) ! 1120: can become (ZERO_EXTRACT x ...). */ ! 1121: if (was_replaced[0] ! 1122: && GET_CODE (to) == TRUNCATE) ! 1123: { ! 1124: #ifdef BITS_BIG_ENDIAN ! 1125: if (GET_CODE (XEXP (x, 2)) == CONST_INT) ! 1126: { ! 1127: if (!undobuf.storage) ! 1128: undobuf.storage = (char *) oballoc (0); ! 1129: /* On a big-endian machine, must increment the bit-number ! 1130: since sign bit is farther away in the pre-truncated value. */ ! 1131: return gen_rtx (ZERO_EXTRACT, GET_MODE (x), ! 1132: XEXP (to, 0), ! 1133: XEXP (x, 1), ! 1134: gen_rtx (CONST_INT, VOIDmode, ! 1135: (INTVAL (XEXP (x, 2)) ! 1136: + GET_MODE_BITSIZE (GET_MODE (XEXP (to, 0))) ! 1137: - GET_MODE_BITSIZE (GET_MODE (to))))); ! 1138: } ! 1139: #else ! 1140: SUBST (XEXP (x, 0), XEXP (to, 0)); ! 1141: #endif ! 1142: } ! 1143: /* Extracting a single bit from the result of a shift: ! 1144: see which bit it was before the shift and extract that directly. */ ! 1145: if (was_replaced[0] ! 1146: && (GET_CODE (to) == ASHIFTRT || GET_CODE (to) == LSHIFTRT ! 1147: || GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT) ! 1148: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1149: && XEXP (x, 1) == const1_rtx ! 1150: && GET_CODE (XEXP (x, 2)) == CONST_INT) ! 1151: { ! 1152: int shift = INTVAL (XEXP (to, 1)); ! 1153: int newpos; ! 1154: if (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT) ! 1155: shift = - shift; ! 1156: #ifdef BITS_BIG_ENDIAN ! 1157: shift = - shift; ! 1158: #endif ! 1159: newpos = INTVAL (XEXP (x, 2)) + shift; ! 1160: if (newpos >= 0 && ! 1161: newpos < GET_MODE_BITSIZE (GET_MODE (to))) ! 1162: { ! 1163: if (!undobuf.storage) ! 1164: undobuf.storage = (char *) oballoc (0); ! 1165: return gen_rtx (ZERO_EXTRACT, GET_MODE (x), ! 1166: XEXP (to, 0), const1_rtx, ! 1167: gen_rtx (CONST_INT, VOIDmode, newpos)); ! 1168: } ! 1169: } ! 1170: break; ! 1171: ! 1172: case LSHIFTRT: ! 1173: case ASHIFTRT: ! 1174: case ROTATE: ! 1175: case ROTATERT: ! 1176: #ifdef SHIFT_COUNT_TRUNCATED ! 1177: /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines). ! 1178: True for all kinds of shifts and also for zero_extend. */ ! 1179: if (was_replaced[1] ! 1180: && (GET_CODE (to) == SIGN_EXTEND ! 1181: || GET_CODE (to) == ZERO_EXTEND) ! 1182: && FAKE_EXTEND_SAFE_P (GET_MODE (to), XEXP (to, 0))) ! 1183: { ! 1184: if (!undobuf.storage) ! 1185: undobuf.storage = (char *) oballoc (0); ! 1186: SUBST (XEXP (x, 1), ! 1187: /* This is a perverse SUBREG, wider than its base. */ ! 1188: gen_lowpart_for_combine (GET_MODE (to), XEXP (to, 0))); ! 1189: } ! 1190: #endif ! 1191: /* Two shifts in a row of same kind ! 1192: in same direction with constant counts ! 1193: may be combined. */ ! 1194: if (was_replaced[0] ! 1195: && GET_CODE (to) == GET_CODE (x) ! 1196: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 1197: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1198: && INTVAL (XEXP (to, 1)) > 0 ! 1199: && INTVAL (XEXP (x, 1)) > 0 ! 1200: && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1)) ! 1201: < GET_MODE_BITSIZE (GET_MODE (x)))) ! 1202: { ! 1203: if (!undobuf.storage) ! 1204: undobuf.storage = (char *) oballoc (0); ! 1205: return gen_rtx (GET_CODE (x), GET_MODE (x), ! 1206: XEXP (to, 0), ! 1207: gen_rtx (CONST_INT, VOIDmode, ! 1208: INTVAL (XEXP (x, 1)) ! 1209: + INTVAL (XEXP (to, 1)))); ! 1210: } ! 1211: break; ! 1212: ! 1213: case LSHIFT: ! 1214: case ASHIFT: ! 1215: #ifdef SHIFT_COUNT_TRUNCATED ! 1216: /* (lshift <X> (sign_extend <Y>)) = (lshift <X> <Y>) (most machines). ! 1217: True for all kinds of shifts and also for zero_extend. */ ! 1218: if (was_replaced[1] ! 1219: && (GET_CODE (to) == SIGN_EXTEND ! 1220: || GET_CODE (to) == ZERO_EXTEND)) ! 1221: { ! 1222: if (!undobuf.storage) ! 1223: undobuf.storage = (char *) oballoc (0); ! 1224: SUBST (XEXP (x, 1), gen_rtx (SUBREG, GET_MODE (to), XEXP (to, 0), 0)); ! 1225: } ! 1226: #endif ! 1227: /* (lshift (and (lshiftrt <foo> <X>) <Y>) <X>) ! 1228: happens copying between bit fields in similar structures. ! 1229: It can be replaced by one and instruction. ! 1230: It does not matter whether the shifts are logical or arithmetic. */ ! 1231: if (GET_CODE (XEXP (x, 0)) == AND ! 1232: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 1233: && INTVAL (XEXP (x, 1)) > 0 ! 1234: && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT ! 1235: && XEXP (XEXP (x, 0), 0) == to ! 1236: && (GET_CODE (to) == LSHIFTRT ! 1237: || GET_CODE (to) == ASHIFTRT) ! 1238: #if 0 ! 1239: /* I now believe this restriction is unnecessary. ! 1240: The outer shift will discard those bits in any case, right? */ ! 1241: ! 1242: /* If inner shift is arithmetic, either it shifts left or ! 1243: the bits it shifts the sign into are zeroed by the and. */ ! 1244: && (INTVAL (XEXP (x, 1)) < 0 ! 1245: || ((unsigned) INTVAL (XEXP (XEXP (x, 0), 1)) ! 1246: < 1 << (GET_MODE_BITSIZE (GET_MODE (x)) ! 1247: - INTVAL (XEXP (x, 0))))) ! 1248: #endif ! 1249: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1250: && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1))) ! 1251: { ! 1252: if (!undobuf.storage) ! 1253: undobuf.storage = (char *) oballoc (0); ! 1254: /* The constant in the new `and' is <Y> << <X> ! 1255: but clear out all bits that don't belong in our mode. */ ! 1256: return gen_rtx (AND, GET_MODE (x), XEXP (to, 0), ! 1257: gen_rtx (CONST_INT, VOIDmode, ! 1258: (GET_MODE_MASK (GET_MODE (x)) ! 1259: & ((GET_MODE_MASK (GET_MODE (x)) ! 1260: & INTVAL (XEXP (XEXP (x, 0), 1))) ! 1261: << INTVAL (XEXP (x, 1)))))); ! 1262: } ! 1263: /* Two shifts in a row in same direction with constant counts ! 1264: may be combined. */ ! 1265: if (was_replaced[0] ! 1266: && (GET_CODE (to) == ASHIFT || GET_CODE (to) == LSHIFT) ! 1267: && GET_CODE (XEXP (x, 1)) == CONST_INT ! 1268: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1269: && INTVAL (XEXP (to, 1)) > 0 ! 1270: && INTVAL (XEXP (x, 1)) > 0 ! 1271: && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (to, 1)) ! 1272: < GET_MODE_BITSIZE (GET_MODE (x)))) ! 1273: { ! 1274: if (!undobuf.storage) ! 1275: undobuf.storage = (char *) oballoc (0); ! 1276: return gen_rtx (GET_CODE (x), GET_MODE (x), ! 1277: XEXP (to, 0), ! 1278: gen_rtx (CONST_INT, VOIDmode, ! 1279: INTVAL (XEXP (x, 1)) ! 1280: + INTVAL (XEXP (to, 1)))); ! 1281: } ! 1282: /* (ashift (ashiftrt <foo> <X>) <X>) ! 1283: (or, on some machines, (ashift (ashift <foo> <-X>) <X>) instead) ! 1284: happens if you divide by 2**N and then multiply by 2**N. ! 1285: It can be replaced by one `and' instruction. ! 1286: It does not matter whether the shifts are logical or arithmetic. */ ! 1287: if (GET_CODE (XEXP (x, 1)) == CONST_INT ! 1288: && INTVAL (XEXP (x, 1)) > 0 ! 1289: && was_replaced[0] ! 1290: && (((GET_CODE (to) == LSHIFTRT || GET_CODE (to) == ASHIFTRT) ! 1291: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1292: && INTVAL (XEXP (x, 1)) == INTVAL (XEXP (to, 1))) ! 1293: || ! 1294: ((GET_CODE (to) == LSHIFT || GET_CODE (to) == ASHIFT) ! 1295: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1296: && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (to, 1))))) ! 1297: { ! 1298: if (!undobuf.storage) ! 1299: undobuf.storage = (char *) oballoc (0); ! 1300: /* The constant in the new `and' is -1 << <X> ! 1301: but clear out all bits that don't belong in our mode. */ ! 1302: return gen_rtx (AND, GET_MODE (x), XEXP (to, 0), ! 1303: gen_rtx (CONST_INT, VOIDmode, ! 1304: (GET_MODE_MASK (GET_MODE (x)) ! 1305: & (GET_MODE_MASK (GET_MODE (x)) ! 1306: << INTVAL (XEXP (x, 1)))))); ! 1307: } ! 1308: ! 1309: } ! 1310: ! 1311: return x; ! 1312: } ! 1313: ! 1314: /* This is the AND case of the function subst. */ ! 1315: ! 1316: static rtx ! 1317: simplify_and_const_int (x, to) ! 1318: rtx x, to; ! 1319: { ! 1320: register rtx varop = XEXP (x, 0); ! 1321: register int constop = INTVAL (XEXP (x, 1)); ! 1322: ! 1323: /* (and (subreg (and <foo> <constant>) 0) <constant>) ! 1324: results from an andsi followed by an andqi, ! 1325: which happens frequently when storing bit-fields ! 1326: on something whose result comes from an andsi. */ ! 1327: if (GET_CODE (varop) == SUBREG ! 1328: && XEXP (varop, 0) == to ! 1329: && subreg_lowpart_p (varop) ! 1330: && GET_CODE (to) == AND ! 1331: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1332: /* Verify that the result of the outer `and' ! 1333: is not affected by any bits not defined in the inner `and'. ! 1334: True if the outer mode is narrower, or if the outer constant ! 1335: masks to zero all the bits that the inner mode doesn't have. */ ! 1336: && (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (GET_MODE (to)) ! 1337: || (constop & ~ GET_MODE_MASK (GET_MODE (to))) == 0)) ! 1338: { ! 1339: if (!undobuf.storage) ! 1340: undobuf.storage = (char *) oballoc (0); ! 1341: return gen_rtx (AND, GET_MODE (x), ! 1342: gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), ! 1343: gen_rtx (CONST_INT, VOIDmode, ! 1344: constop ! 1345: /* Remember that the bits outside that mode ! 1346: are not being changed, so the effect ! 1347: is as if they were all 1. */ ! 1348: & INTVAL (XEXP (to, 1)))); ! 1349: } ! 1350: /* (and:SI (zero_extract:SI ...) <constant>) ! 1351: results from an andsi following a byte-fetch on risc machines. ! 1352: When the constant includes all bits extracted, eliminate the `and'. */ ! 1353: if (GET_CODE (varop) == ZERO_EXTRACT ! 1354: && GET_CODE (XEXP (varop, 1)) == CONST_INT ! 1355: /* The `and' must not clear any bits that the extract can give. */ ! 1356: && (~ constop & ((1 << INTVAL (XEXP (varop, 1))) - 1)) == 0) ! 1357: return varop; ! 1358: /* (and (zero_extend <foo>) <constant>) ! 1359: often results from storing in a bit-field something ! 1360: that was calculated as a short. Replace with a single `and' ! 1361: in whose constant all bits not in <foo>'s mode are zero. */ ! 1362: if (varop == to ! 1363: && GET_CODE (to) == ZERO_EXTEND ! 1364: && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))) ! 1365: { ! 1366: if (!undobuf.storage) ! 1367: undobuf.storage = (char *) oballoc (0); ! 1368: return gen_rtx (AND, GET_MODE (x), ! 1369: /* This is a perverse SUBREG, wider than its base. */ ! 1370: gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), ! 1371: gen_rtx (CONST_INT, VOIDmode, ! 1372: constop & GET_MODE_MASK (GET_MODE (XEXP (to, 0))))); ! 1373: } ! 1374: /* (and (sign_extend <foo>) <constant>) ! 1375: can be replaced with (and (subreg <foo>) <constant>) ! 1376: if <constant> is narrower than <foo>'s mode, ! 1377: or with (zero_extend <foo>) if <constant> is a mask for that mode. */ ! 1378: if (varop == to ! 1379: && GET_CODE (to) == SIGN_EXTEND ! 1380: && ((unsigned) constop <= GET_MODE_MASK (GET_MODE (XEXP (to, 0)))) ! 1381: && FAKE_EXTEND_SAFE_P (GET_MODE (x), XEXP (to, 0))) ! 1382: { ! 1383: if (!undobuf.storage) ! 1384: undobuf.storage = (char *) oballoc (0); ! 1385: if (constop == GET_MODE_MASK (GET_MODE (XEXP (to, 0)))) ! 1386: return gen_rtx (ZERO_EXTEND, GET_MODE (x), XEXP (to, 0)); ! 1387: return gen_rtx (AND, GET_MODE (x), ! 1388: /* This is a perverse SUBREG, wider than its base. */ ! 1389: gen_lowpart_for_combine (GET_MODE (x), XEXP (to, 0)), ! 1390: XEXP (x, 1)); ! 1391: } ! 1392: /* (and (and <foo> <constant>) <constant>) ! 1393: comes from two and instructions in a row. */ ! 1394: if (varop == to ! 1395: && GET_CODE (to) == AND ! 1396: && GET_CODE (XEXP (to, 1)) == CONST_INT) ! 1397: { ! 1398: if (!undobuf.storage) ! 1399: undobuf.storage = (char *) oballoc (0); ! 1400: return gen_rtx (AND, GET_MODE (x), ! 1401: XEXP (to, 0), ! 1402: gen_rtx (CONST_INT, VOIDmode, ! 1403: constop ! 1404: & INTVAL (XEXP (to, 1)))); ! 1405: } ! 1406: /* (and (ashiftrt (ashift FOO N) N) CONST) ! 1407: may be simplified to (and FOO CONST) if CONST masks off the bits ! 1408: changed by the two shifts. */ ! 1409: if (GET_CODE (varop) == ASHIFTRT ! 1410: && GET_CODE (XEXP (varop, 1)) == CONST_INT ! 1411: && XEXP (varop, 0) == to ! 1412: && GET_CODE (to) == ASHIFT ! 1413: && GET_CODE (XEXP (to, 1)) == CONST_INT ! 1414: && INTVAL (XEXP (varop, 1)) == INTVAL (XEXP (to, 1)) ! 1415: && ((unsigned) constop >> INTVAL (XEXP (varop, 1))) == 0) ! 1416: { ! 1417: if (!undobuf.storage) ! 1418: undobuf.storage = (char *) oballoc (0); ! 1419: /* If CONST is a mask for the low byte, ! 1420: change this into a zero-extend instruction ! 1421: from just the low byte of FOO. */ ! 1422: if (constop == GET_MODE_MASK (QImode)) ! 1423: { ! 1424: rtx temp = gen_lowpart_for_combine (QImode, XEXP (to, 0)); ! 1425: if (GET_CODE (temp) != CLOBBER) ! 1426: return gen_rtx (ZERO_EXTEND, GET_MODE (x), temp); ! 1427: } ! 1428: return gen_rtx (AND, GET_MODE (x), ! 1429: XEXP (to, 0), XEXP (x, 1)); ! 1430: } ! 1431: /* (and x const) may be converted to (zero_extend (subreg x 0)). */ ! 1432: if (constop == GET_MODE_MASK (QImode)) ! 1433: { ! 1434: if (!undobuf.storage) ! 1435: undobuf.storage = (char *) oballoc (0); ! 1436: return gen_rtx (ZERO_EXTEND, GET_MODE (x), ! 1437: gen_rtx (SUBREG, QImode, varop, 0)); ! 1438: } ! 1439: if (constop == GET_MODE_MASK (HImode)) ! 1440: { ! 1441: if (!undobuf.storage) ! 1442: undobuf.storage = (char *) oballoc (0); ! 1443: return gen_rtx (ZERO_EXTEND, GET_MODE (x), ! 1444: gen_rtx (SUBREG, HImode, varop, 0)); ! 1445: } ! 1446: /* No simplification applies. */ ! 1447: return 0; ! 1448: } ! 1449: ! 1450: /* Like gen_lowpart but for use by combine. In combine it is not possible ! 1451: to create any new pseudoregs. However, it is safe to create ! 1452: invalid memory addresses, because combine will try to recognize ! 1453: them and all they will do is make the combine attempt fail. ! 1454: ! 1455: If for some reason this cannot do its job, an rtx ! 1456: (clobber (const_int 0)) is returned. ! 1457: An insn containing that will not be recognized. */ ! 1458: ! 1459: #undef gen_lowpart ! 1460: ! 1461: static rtx ! 1462: gen_lowpart_for_combine (mode, x) ! 1463: enum machine_mode mode; ! 1464: register rtx x; ! 1465: { ! 1466: if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG) ! 1467: return gen_lowpart (mode, x); ! 1468: if (GET_MODE (x) == mode || x->volatil) ! 1469: return gen_rtx (CLOBBER, VOIDmode, const0_rtx); ! 1470: if (GET_CODE (x) == MEM) ! 1471: { ! 1472: register int offset = 0; ! 1473: #ifdef WORDS_BIG_ENDIAN ! 1474: offset = (max (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) ! 1475: - max (GET_MODE_SIZE (mode), UNITS_PER_WORD)); ! 1476: #endif ! 1477: #ifdef BYTES_BIG_ENDIAN ! 1478: /* Adjust the address so that the address-after-the-data ! 1479: is unchanged. */ ! 1480: offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (mode)) ! 1481: - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); ! 1482: #endif ! 1483: return gen_rtx (MEM, mode, plus_constant (XEXP (x, 0), ! 1484: offset)); ! 1485: } ! 1486: else ! 1487: return gen_rtx (CLOBBER, VOIDmode, const0_rtx); ! 1488: } ! 1489: ! 1490: /* After substitution, if the resulting pattern looks like ! 1491: (set (cc0) (and ...)) or (set (cc0) (lshiftrt ...)), ! 1492: this function is called to simplify the ! 1493: pattern into a bit-field operation if possible. */ ! 1494: ! 1495: static void ! 1496: simplify_set_cc0_and (insn) ! 1497: rtx insn; ! 1498: { ! 1499: register rtx value = XEXP (PATTERN (insn), 1); ! 1500: register rtx op0 = XEXP (value, 0); ! 1501: register rtx op1 = XEXP (value, 1); ! 1502: int offset = 0; ! 1503: rtx var = 0; ! 1504: rtx bitnum = 0; ! 1505: int temp; ! 1506: int unit; ! 1507: rtx newpat; ! 1508: ! 1509: if (GET_CODE (value) == AND) ! 1510: { ! 1511: op0 = XEXP (value, 0); ! 1512: op1 = XEXP (value, 1); ! 1513: } ! 1514: else if (GET_CODE (value) == LSHIFTRT) ! 1515: { ! 1516: /* If there is no AND, but there is a shift that discards ! 1517: all but the sign bit, we can pretend that the shift result ! 1518: is ANDed with 1. Otherwise we cannot handle just a shift. */ ! 1519: if (GET_CODE (XEXP (value, 1)) == CONST_INT ! 1520: && (INTVAL (XEXP (value, 1)) ! 1521: == GET_MODE_BITSIZE (GET_MODE (value)) - 1)) ! 1522: { ! 1523: op0 = value; ! 1524: op1 = const1_rtx; ! 1525: } ! 1526: else ! 1527: return; ! 1528: } ! 1529: else ! 1530: abort (); ! 1531: ! 1532: /* Look for a constant power of 2 or a shifted 1 ! 1533: on either side of the AND. Set VAR to the other side. ! 1534: Set BITNUM to the shift count of the 1 (as an rtx). ! 1535: Or, if bit number is constant, set OFFSET to the bit number. */ ! 1536: ! 1537: switch (GET_CODE (op0)) ! 1538: { ! 1539: case CONST_INT: ! 1540: temp = exact_log2 (INTVAL (op0)); ! 1541: if (temp < 0) ! 1542: return; ! 1543: offset = temp; ! 1544: var = op1; ! 1545: break; ! 1546: ! 1547: case ASHIFT: ! 1548: case LSHIFT: ! 1549: if (XEXP (op0, 0) == const1_rtx) ! 1550: { ! 1551: bitnum = XEXP (op0, 1); ! 1552: var = op1; ! 1553: } ! 1554: } ! 1555: if (var == 0) ! 1556: switch (GET_CODE (op1)) ! 1557: { ! 1558: case CONST_INT: ! 1559: temp = exact_log2 (INTVAL (op1)); ! 1560: if (temp < 0) ! 1561: return; ! 1562: offset = temp; ! 1563: var = op0; ! 1564: break; ! 1565: ! 1566: case ASHIFT: ! 1567: case LSHIFT: ! 1568: if (XEXP (op1, 0) == const1_rtx) ! 1569: { ! 1570: bitnum = XEXP (op1, 1); ! 1571: var = op0; ! 1572: } ! 1573: } ! 1574: ! 1575: /* If VAR is 0, we didn't find something recognizable. */ ! 1576: if (var == 0) ! 1577: return; ! 1578: ! 1579: if (!undobuf.storage) ! 1580: undobuf.storage = (char *) oballoc (0); ! 1581: ! 1582: /* If the bit position is currently exactly 0, ! 1583: extract a right-shift from the variable portion. */ ! 1584: if (offset == 0 ! 1585: && (GET_CODE (var) == ASHIFTRT || GET_CODE (var) == LSHIFTRT)) ! 1586: { ! 1587: bitnum = XEXP (var, 1); ! 1588: var = XEXP (var, 0); ! 1589: } ! 1590: ! 1591: if (GET_CODE (var) == SUBREG && SUBREG_WORD (var) == 0) ! 1592: var = SUBREG_REG (var); ! 1593: ! 1594: /* Note that BITNUM and OFFSET are always little-endian thru here ! 1595: even on a big-endian machine. */ ! 1596: ! 1597: #ifdef BITS_BIG_ENDIAN ! 1598: unit = GET_MODE_BITSIZE (GET_MODE (var)) - 1; ! 1599: ! 1600: if (bitnum != 0) ! 1601: bitnum = gen_rtx (MINUS, SImode, ! 1602: gen_rtx (CONST_INT, VOIDmode, unit), bitnum); ! 1603: else ! 1604: offset = unit - offset; ! 1605: #endif ! 1606: ! 1607: if (bitnum == 0) ! 1608: bitnum = gen_rtx (CONST_INT, VOIDmode, offset); ! 1609: ! 1610: newpat = gen_rtx (SET, VOIDmode, cc0_rtx, ! 1611: gen_rtx (ZERO_EXTRACT, VOIDmode, var, const1_rtx, bitnum)); ! 1612: if (recog (newpat, insn) >= 0) ! 1613: { ! 1614: if (undobuf.num_undo < MAX_UNDO) ! 1615: { ! 1616: undobuf.undo[undobuf.num_undo].where = &XEXP (PATTERN (insn), 1); ! 1617: undobuf.undo[undobuf.num_undo].old_contents = value; ! 1618: XEXP (PATTERN (insn), 1) = XEXP (newpat, 1); ! 1619: } ! 1620: undobuf.num_undo++; ! 1621: } ! 1622: } ! 1623: ! 1624: /* Update the records of when each REG was most recently set or killed ! 1625: for the things done by INSN. This is the last thing done in processing ! 1626: INSN in the combiner loop. ! 1627: ! 1628: We update reg_last_set, reg_last_death, and also the similar information ! 1629: mem_last_set (which insn most recently modified memory) ! 1630: and last_call_cuid (which insn was the most recent subroutine call). */ ! 1631: ! 1632: static void ! 1633: record_dead_and_set_regs (insn) ! 1634: rtx insn; ! 1635: { ! 1636: register rtx link; ! 1637: for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) ! 1638: { ! 1639: if (REG_NOTE_KIND (link) == REG_DEAD) ! 1640: reg_last_death[REGNO (XEXP (link, 0))] = insn; ! 1641: else if (REG_NOTE_KIND (link) == REG_INC) ! 1642: reg_last_set[REGNO (XEXP (link, 0))] = insn; ! 1643: } ! 1644: ! 1645: if (GET_CODE (insn) == CALL_INSN) ! 1646: last_call_cuid = mem_last_set = INSN_CUID (insn); ! 1647: ! 1648: if (GET_CODE (PATTERN (insn)) == PARALLEL) ! 1649: { ! 1650: register int i; ! 1651: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) ! 1652: { ! 1653: register rtx elt = XVECEXP (PATTERN (insn), 0, i); ! 1654: register enum rtx_code code = GET_CODE (elt); ! 1655: if (code == SET || code == CLOBBER) ! 1656: { ! 1657: if (GET_CODE (XEXP (elt, 0)) == REG) ! 1658: reg_last_set[REGNO (XEXP (elt, 0))] = insn; ! 1659: if (GET_CODE (XEXP (elt, 0)) == SUBREG ! 1660: && GET_CODE (SUBREG_REG (XEXP (elt, 0))) == REG) ! 1661: reg_last_set[REGNO (SUBREG_REG (XEXP (elt, 0)))] = insn; ! 1662: else if (GET_CODE (XEXP (elt, 0)) == MEM) ! 1663: mem_last_set = INSN_CUID (insn); ! 1664: } ! 1665: } ! 1666: } ! 1667: else if (GET_CODE (PATTERN (insn)) == SET ! 1668: || GET_CODE (PATTERN (insn)) == CLOBBER) ! 1669: { ! 1670: register rtx x = XEXP (PATTERN (insn), 0); ! 1671: if (GET_CODE (x) == REG) ! 1672: reg_last_set[REGNO (x)] = insn; ! 1673: if (GET_CODE (x) == SUBREG ! 1674: && GET_CODE (SUBREG_REG (x)) == REG) ! 1675: reg_last_set[REGNO (SUBREG_REG (x))] = insn; ! 1676: else if (GET_CODE (x) == MEM) ! 1677: mem_last_set = INSN_CUID (insn); ! 1678: } ! 1679: } ! 1680: ! 1681: /* Return nonzero if expression X refers to a REG or to memory ! 1682: that is set in an instruction more recent than FROM_CUID. */ ! 1683: ! 1684: static int ! 1685: use_crosses_set_p (x, from_cuid) ! 1686: register rtx x; ! 1687: int from_cuid; ! 1688: { ! 1689: register char *fmt; ! 1690: register int i; ! 1691: register enum rtx_code code = GET_CODE (x); ! 1692: ! 1693: if (code == REG) ! 1694: { ! 1695: register int regno = REGNO (x); ! 1696: return (reg_last_set[regno] ! 1697: && INSN_CUID (reg_last_set[regno]) > from_cuid); ! 1698: } ! 1699: ! 1700: if (code == MEM && mem_last_set > from_cuid) ! 1701: return 1; ! 1702: ! 1703: fmt = GET_RTX_FORMAT (code); ! 1704: ! 1705: for (i = GET_RTX_LENGTH (code); i >= 0; i--) ! 1706: { ! 1707: if (fmt[i] == 'E') ! 1708: { ! 1709: register int j; ! 1710: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 1711: if (use_crosses_set_p (XVECEXP (x, i, j), from_cuid)) ! 1712: return 1; ! 1713: } ! 1714: else if (fmt[i] == 'e' ! 1715: && use_crosses_set_p (XEXP (x, i), from_cuid)) ! 1716: return 1; ! 1717: } ! 1718: return 0; ! 1719: } ! 1720: ! 1721: /* Return nonzero if reg REGNO is marked as dying in INSN. */ ! 1722: ! 1723: int ! 1724: regno_dead_p (regno, insn) ! 1725: int regno; ! 1726: rtx insn; ! 1727: { ! 1728: register rtx link; ! 1729: ! 1730: for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) ! 1731: if ((REG_NOTE_KIND (link) == REG_DEAD ! 1732: || REG_NOTE_KIND (link) == REG_INC) ! 1733: && REGNO (XEXP (link, 0)) == regno) ! 1734: return 1; ! 1735: ! 1736: return 0; ! 1737: } ! 1738: ! 1739: /* Remove register number REGNO from the dead registers list of INSN. */ ! 1740: ! 1741: static void ! 1742: remove_death (regno, insn) ! 1743: int regno; ! 1744: rtx insn; ! 1745: { ! 1746: register rtx link, next; ! 1747: while ((link = REG_NOTES (insn)) ! 1748: && REG_NOTE_KIND (link) == REG_DEAD ! 1749: && REGNO (XEXP (link, 0)) == regno) ! 1750: REG_NOTES (insn) = XEXP (link, 1); ! 1751: ! 1752: if (link) ! 1753: while (next = XEXP (link, 1)) ! 1754: { ! 1755: if (REG_NOTE_KIND (next) == REG_DEAD ! 1756: && REGNO (XEXP (next, 0)) == regno) ! 1757: XEXP (link, 1) = XEXP (next, 1); ! 1758: else ! 1759: link = next; ! 1760: } ! 1761: } ! 1762: ! 1763: /* Return nonzero if J is the first insn following I, ! 1764: not counting labels, line numbers, etc. ! 1765: We assume that J follows I. */ ! 1766: ! 1767: static int ! 1768: adjacent_insns_p (i, j) ! 1769: rtx i, j; ! 1770: { ! 1771: register rtx insn; ! 1772: for (insn = NEXT_INSN (i); insn != j; insn = NEXT_INSN (insn)) ! 1773: if (GET_CODE (insn) == INSN ! 1774: || GET_CODE (insn) == CALL_INSN ! 1775: || GET_CODE (insn) == JUMP_INSN) ! 1776: return 0; ! 1777: return 1; ! 1778: } ! 1779: ! 1780: /* Concatenate the list of logical links of OINSN ! 1781: into INSN's list of logical links. ! 1782: Modifies OINSN destructively. ! 1783: ! 1784: If ALL_LINKS is nonzero, move all the links that OINSN has. ! 1785: Otherwise, move only those that point to insns that set regs ! 1786: that die in the insn OINSN. ! 1787: Other links are clobbered so that they are no longer effective. */ ! 1788: ! 1789: static void ! 1790: add_links (insn, oinsn, all_links) ! 1791: rtx insn, oinsn; ! 1792: int all_links; ! 1793: { ! 1794: register rtx links = LOG_LINKS (oinsn); ! 1795: if (! all_links) ! 1796: { ! 1797: rtx tail; ! 1798: for (tail = links; tail; tail = XEXP (tail, 1)) ! 1799: { ! 1800: rtx target = XEXP (tail, 0); ! 1801: if (GET_CODE (target) != INSN ! 1802: || GET_CODE (PATTERN (target)) != SET ! 1803: || GET_CODE (SET_DEST (PATTERN (target))) != REG ! 1804: || ! dead_or_set_p (oinsn, SET_DEST (PATTERN (target)))) ! 1805: /* OINSN is going to become a NOTE ! 1806: so a link pointing there will have no effect. */ ! 1807: XEXP (tail, 0) = oinsn; ! 1808: } ! 1809: } ! 1810: if (LOG_LINKS (insn) == 0) ! 1811: LOG_LINKS (insn) = links; ! 1812: else ! 1813: { ! 1814: register rtx next, prev = LOG_LINKS (insn); ! 1815: while (next = XEXP (prev, 1)) ! 1816: prev = next; ! 1817: XEXP (prev, 1) = links; ! 1818: } ! 1819: } ! 1820: ! 1821: /* Concatenate the any elements of the list of reg-notes INCS ! 1822: which are of type REG_INC ! 1823: into INSN's list of reg-notes. */ ! 1824: ! 1825: static void ! 1826: add_incs (insn, incs) ! 1827: rtx insn, incs; ! 1828: { ! 1829: register rtx tail; ! 1830: ! 1831: for (tail = incs; tail; tail = XEXP (tail, 1)) ! 1832: if (REG_NOTE_KIND (tail) == REG_INC) ! 1833: REG_NOTES (insn) ! 1834: = gen_rtx (EXPR_LIST, REG_INC, XEXP (tail, 0), REG_NOTES (insn)); ! 1835: } ! 1836: ! 1837: /* For each register (hardware or pseudo) used within expression X, ! 1838: if its death is in an instruction with cuid ! 1839: between FROM_CUID (inclusive) and TO_INSN (exclusive), ! 1840: mark it as dead in TO_INSN instead. ! 1841: ! 1842: This is done when X is being merged by combination into TO_INSN. */ ! 1843: ! 1844: static void ! 1845: move_deaths (x, from_cuid, to_insn) ! 1846: rtx x; ! 1847: int from_cuid; ! 1848: rtx to_insn; ! 1849: { ! 1850: register char *fmt; ! 1851: register int len, i; ! 1852: register enum rtx_code code = GET_CODE (x); ! 1853: ! 1854: if (code == REG) ! 1855: { ! 1856: register rtx where_dead = reg_last_death[REGNO (x)]; ! 1857: ! 1858: if (where_dead && INSN_CUID (where_dead) >= from_cuid ! 1859: && INSN_CUID (where_dead) < INSN_CUID (to_insn)) ! 1860: { ! 1861: remove_death (REGNO (x), reg_last_death[REGNO (x)]); ! 1862: if (! dead_or_set_p (to_insn, x)) ! 1863: REG_NOTES (to_insn) ! 1864: = gen_rtx (EXPR_LIST, REG_DEAD, x, REG_NOTES (to_insn)); ! 1865: } ! 1866: return; ! 1867: } ! 1868: ! 1869: len = GET_RTX_LENGTH (code); ! 1870: fmt = GET_RTX_FORMAT (code); ! 1871: ! 1872: for (i = 0; i < len; i++) ! 1873: { ! 1874: if (fmt[i] == 'E') ! 1875: { ! 1876: register int j; ! 1877: for (j = XVECLEN (x, i) - 1; j >= 0; j--) ! 1878: move_deaths (XVECEXP (x, i, j), from_cuid, to_insn); ! 1879: } ! 1880: else if (fmt[i] == 'e') ! 1881: move_deaths (XEXP (x, i), from_cuid, to_insn); ! 1882: } ! 1883: } ! 1884: ! 1885: void ! 1886: dump_combine_stats (file) ! 1887: char *file; ! 1888: { ! 1889: fprintf ! 1890: (file, ! 1891: ";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n" ! 1892: , combine_attempts, combine_merges, combine_extras, combine_successes); ! 1893: } ! 1894: ! 1895: void ! 1896: dump_combine_total_stats (file) ! 1897: char *file; ! 1898: { ! 1899: fprintf ! 1900: (file, ! 1901: "\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n", ! 1902: total_attempts, total_merges, total_extras, total_successes); ! 1903: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.