|
|
1.1 ! root 1: /* Move constant computations out of loops. ! 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 is the loop optimization pass of the compiler. ! 23: It finds invariant computations within loops and moves them ! 24: to the beginning of the loop. ! 25: ! 26: It also finds cases where ! 27: a register is set within the loop by zero-extending a narrower value ! 28: and changes these to zero the entire register once before the loop ! 29: and merely copy the low part within the loop. ! 30: ! 31: Most of the complexity is in heuristics to decide when it is worth ! 32: while to do these things. */ ! 33: ! 34: /* ??? verify_loop would run faster if we made one table ! 35: of the minimum and maximum luids from which each label is reached. ! 36: Also, it would be faster if loop_store_addrs were a hash table. */ ! 37: ! 38: #include "config.h" ! 39: #include "rtl.h" ! 40: #include "insn-config.h" ! 41: #include "regs.h" ! 42: #include "recog.h" ! 43: #include <stdio.h> ! 44: ! 45: /* Vector mapping INSN_UIDs to luids. ! 46: The luids are like uids but increase monononically always. ! 47: We use them to see whether a jump comes from outside a given loop. */ ! 48: ! 49: static short *uid_luid; ! 50: ! 51: /* Get the luid of an insn. */ ! 52: ! 53: #define INSN_LUID(INSN) (uid_luid[INSN_UID (INSN)]) ! 54: ! 55: /* 1 + largest uid of any insn. */ ! 56: ! 57: static int max_uid; ! 58: ! 59: /* 1 + luid of last insn. */ ! 60: ! 61: static int max_luid; ! 62: ! 63: /* Nonzero if somewhere in the current loop ! 64: there is either a subroutine call, ! 65: or a store into a memory address that is not fixed, ! 66: or a store in a BLKmode memory operand, ! 67: or too many different fixed addresses stored in ! 68: to record them all in `loop_store_addrs'. ! 69: ! 70: In any of these cases, no memory location can be regarded ! 71: as invariant. */ ! 72: ! 73: static int unknown_address_altered; ! 74: ! 75: /* Nonzero if somewhere in the current loop there is a store ! 76: into a memory address that is not fixed but is known to be ! 77: part of an aggregate. ! 78: ! 79: In this case, no memory reference in an aggregate may be ! 80: considered invariant. */ ! 81: ! 82: static int unknown_aggregate_altered; ! 83: ! 84: /* Nonzero if somewhere in the current loop there is a store ! 85: into a memory address other than a fixed address not in an aggregate. ! 86: ! 87: In this case, no memory reference in an aggregate at a varying address ! 88: may be considered invariant. */ ! 89: ! 90: static int fixed_aggregate_altered; ! 91: ! 92: /* Nonzero if there is a subroutine call in the current loop. ! 93: (unknown_address_altered is also nonzero in this case.) */ ! 94: ! 95: static int loop_has_call; ! 96: ! 97: /* Array of fixed memory addresses that are stored in this loop. ! 98: If there are too many to fit here, ! 99: we just turn on unknown_address_altered. */ ! 100: ! 101: #define NUM_STORES 10 ! 102: static rtx loop_store_addrs[NUM_STORES]; ! 103: static int loop_store_widths[NUM_STORES]; ! 104: ! 105: /* Index of first available slot in above array. */ ! 106: static int loop_store_addrs_idx; ! 107: ! 108: /* During the analysis of a loop, a chain of `struct movable's ! 109: is made to record all the movable insns found. ! 110: Then the entire chain can be scanned to decide which to move. */ ! 111: ! 112: struct movable ! 113: { ! 114: rtx insn; /* A movable insn */ ! 115: int consec; /* Number of consecutive following insns ! 116: that must be moved with this one. */ ! 117: int regno; /* The register it sets */ ! 118: short lifetime; /* lifetime of that register; ! 119: may be adjusted when matching movables ! 120: that load the same value are found. */ ! 121: short times_used; /* Number of times the register is used, ! 122: plus uses of related insns that could ! 123: be moved if this one is. */ ! 124: unsigned int cond : 1; /* 1 if only conditionally movable */ ! 125: unsigned int force : 1; /* 1 means MUST move this insn */ ! 126: unsigned int global : 1; /* 1 means reg is live outside this loop */ ! 127: unsigned int done : 1; /* 1 inhibits further processing of this */ ! 128: unsigned int partial : 1; /* Moving this doesn't make it invariant. */ ! 129: struct movable *match; /* First entry for same value */ ! 130: struct movable *forces; /* An insn that must be moved if this is */ ! 131: struct movable *next; ! 132: }; ! 133: ! 134: static FILE *loop_dump_stream; ! 135: ! 136: static rtx verify_loop (); ! 137: static int invariant_p (); ! 138: static int can_jump_into_range_p (); ! 139: static void count_loop_regs_set (); ! 140: static void note_addr_stored (); ! 141: static int loop_reg_used_before_p (); ! 142: static void constant_high_bytes (); ! 143: static void scan_loop (); ! 144: static rtx replace_regs (); ! 145: static void move_movables (); ! 146: static int may_trap_p (); ! 147: ! 148: /* Entry point of this file. Perform loop optimization ! 149: on the current function. F is the first insn of the function ! 150: and NREGS is the number of register numbers used. */ ! 151: ! 152: void ! 153: loop_optimize (f, nregs, dumpfile) ! 154: /* f is the first instruction of a chain of insns for one function */ ! 155: rtx f; ! 156: /* nregs is the total number of registers used in it */ ! 157: int nregs; ! 158: FILE *dumpfile; ! 159: { ! 160: register rtx insn; ! 161: register int i; ! 162: rtx end; ! 163: rtx last_insn; ! 164: ! 165: loop_dump_stream = dumpfile; ! 166: ! 167: init_recog (); ! 168: ! 169: /* First find the last real insn, and count the number of insns, ! 170: and assign insns their suids. */ ! 171: ! 172: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn)) ! 173: if (INSN_UID (insn) > i) ! 174: i = INSN_UID (insn); ! 175: ! 176: max_uid = i + 1; ! 177: uid_luid = (short *) alloca ((i + 1) * sizeof (short)); ! 178: bzero (uid_luid, (i + 1) * sizeof (short)); ! 179: ! 180: /* Compute the mapping from uids to luids. ! 181: LUIDs are numbers assigned to insns, like uids, ! 182: except that luids increase monotonically through the code. */ ! 183: ! 184: for (insn = f, i = 0; insn; insn = NEXT_INSN (insn)) ! 185: { ! 186: last_insn = insn; ! 187: INSN_LUID (insn) = ++i; ! 188: } ! 189: ! 190: max_luid = i; ! 191: ! 192: /* Don't leave gaps in uid_luid for insns that have been ! 193: deleted. It is possible that the first or last insn ! 194: using some register has been deleted by cross-jumping. ! 195: Make sure that uid_luid for that former insn's uid ! 196: points to the general area where that insn used to be. */ ! 197: for (i = 0; i < max_uid; i++) ! 198: { ! 199: uid_luid[0] = uid_luid[i]; ! 200: if (uid_luid[0] != 0) ! 201: break; ! 202: } ! 203: for (i = 0; i < max_uid; i++) ! 204: if (uid_luid[i] == 0) ! 205: uid_luid[i] = uid_luid[i - 1]; ! 206: ! 207: /* Find and process each loop. ! 208: We scan from the end, and process each loop when its start is seen, ! 209: so we process innermost loops first. */ ! 210: ! 211: for (insn = last_insn; insn; insn = PREV_INSN (insn)) ! 212: if (GET_CODE (insn) == NOTE ! 213: && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG ! 214: /* Make sure it really is a loop -- no jumps in from outside. */ ! 215: && (end = verify_loop (f, insn))) ! 216: scan_loop (insn, end, nregs); ! 217: } ! 218: ! 219: /* Optimize one loop whose start is LOOP_START and end is END. ! 220: LOOP_START is the NOTE_INSN_LOOP_BEG and END is the matching ! 221: NOTE_INSN_LOOP_END. */ ! 222: ! 223: static void ! 224: scan_loop (loop_start, end, nregs) ! 225: rtx loop_start, end; ! 226: int nregs; ! 227: { ! 228: register int i; ! 229: register rtx p = NEXT_INSN (loop_start); ! 230: /* 1 if we are scanning insns that could be executed zero times. */ ! 231: int maybe_never = 0; ! 232: /* 1 if we are scanning insns that might never be executed ! 233: due to a subroutine call which might exit before they are reached. */ ! 234: int call_passed = 0; ! 235: /* For a rotated loop that is entered near the bottom, ! 236: this is the label at the top. Otherwise it is zero. */ ! 237: rtx loop_top = 0; ! 238: /* This is the insn (whatever kind) before the NOTE that starts the loop. ! 239: Any insns moved out of the loop will follow it. */ ! 240: rtx before_start = PREV_INSN (loop_start); ! 241: /* Jump insn that enters the loop, or 0 if control drops in. */ ! 242: rtx loop_entry_jump = 0; ! 243: /* Place in the loop where control enters. */ ! 244: rtx scan_start; ! 245: /* Number of insns in the loop. */ ! 246: int insn_count; ! 247: int tem; ! 248: /* Indexed by register number, contains the number of times the reg ! 249: is set during the loop being scanned, or -1 if the insns that set it ! 250: have all been scanned as candidates for being moved out of the loop. ! 251: 0 indicates an invariant register; -1 a conditionally invariant one. */ ! 252: short *n_times_set; ! 253: /* Indexed by register number, contains the number of times the reg ! 254: was used during the loop being scanned, not counting changes due ! 255: to moving these insns out of the loop. */ ! 256: short *n_times_used; ! 257: /* Indexed by register number, contains 1 for a register whose ! 258: assignments may not be moved out of the loop. */ ! 259: char *may_not_move; ! 260: /* Chain describing insns movable in current loop. */ ! 261: struct movable *movables = 0; ! 262: /* Last element in `movables' -- so we can add elements at the end. */ ! 263: struct movable *last_movable = 0; ! 264: /* Ratio of extra register life span we can justify ! 265: for saving an instruction. More if loop doesn't call subroutines ! 266: since in that case saving an insn makes more difference ! 267: and more registers are available. */ ! 268: int threshold = loop_has_call ? 17 : 34; ! 269: ! 270: n_times_set = (short *) alloca (nregs * sizeof (short)); ! 271: n_times_used = (short *) alloca (nregs * sizeof (short)); ! 272: may_not_move = (char *) alloca (nregs); ! 273: ! 274: /* Determine whether this loop starts with a jump down ! 275: to a test at the end. */ ! 276: while (p != end ! 277: && GET_CODE (p) != CODE_LABEL && GET_CODE (p) != JUMP_INSN) ! 278: p = NEXT_INSN (p); ! 279: ! 280: /* "Loop" contains neither jumps nor labels; ! 281: it must have been a dummy. Think no more about it. */ ! 282: if (p == end) ! 283: return; ! 284: ! 285: scan_start = p; ! 286: ! 287: /* If loop has a jump before the first label, ! 288: the true entry is the target of that jump. ! 289: Start scan from there. ! 290: But record in LOOP_TOP the place where the end-test jumps ! 291: back to so we can scan that after the end of the loop. */ ! 292: if (GET_CODE (p) == JUMP_INSN) ! 293: { ! 294: loop_entry_jump = p; ! 295: loop_top = NEXT_INSN (p); ! 296: /* Loop entry will never be a conditional jump. ! 297: If we see one, this must not be a real loop. */ ! 298: if (GET_CODE (loop_top) != BARRIER) ! 299: return; ! 300: p = JUMP_LABEL (p); ! 301: /* Check to see whether the jump actually ! 302: jumps out of the loop (meaning it's no loop). ! 303: This case can happen for things like ! 304: do {..} while (0). */ ! 305: if (p == 0 ! 306: || INSN_LUID (p) < INSN_LUID (loop_start) ! 307: || INSN_LUID (p) >= INSN_LUID (end)) ! 308: { ! 309: if (loop_dump_stream) ! 310: fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n", ! 311: INSN_UID (loop_start), INSN_UID (end)); ! 312: return; ! 313: } ! 314: ! 315: /* Find the first label after the entry-jump. */ ! 316: while (GET_CODE (loop_top) != CODE_LABEL) ! 317: { ! 318: loop_top = NEXT_INSN (loop_top); ! 319: if (loop_top == 0) ! 320: abort (); ! 321: } ! 322: ! 323: /* Maybe rearrange the loop to drop straight in ! 324: with a new test to jump around it entirely. ! 325: (The latter is considered outside the loop.) ! 326: If this is done, we no longer enter with a jump. */ ! 327: if (loop_skip_over (loop_start, end, loop_entry_jump)) ! 328: loop_top = 0; ! 329: else ! 330: /* We really do enter with a jump; ! 331: scan the loop from the place where the jump jumps to. */ ! 332: scan_start = p; ! 333: } ! 334: ! 335: /* Count number of times each reg is set during this loop. ! 336: Set MAY_NOT_MOVE[I] if it is not safe to move out ! 337: the setting of register I. */ ! 338: ! 339: bzero (n_times_set, nregs * sizeof (short)); ! 340: bzero (may_not_move, nregs); ! 341: count_loop_regs_set (loop_top ? loop_top : loop_start, end, ! 342: n_times_set, may_not_move, ! 343: &insn_count, nregs); ! 344: for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) ! 345: may_not_move[i] = 1, n_times_set[i] = 1; ! 346: bcopy (n_times_set, n_times_used, nregs * sizeof (short)); ! 347: ! 348: if (loop_dump_stream) ! 349: fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns\n\n", ! 350: INSN_UID (loop_start), INSN_UID (end), insn_count); ! 351: ! 352: /* Scan through the loop finding insns that are safe to move. ! 353: In each such insn, store QImode as the mode, to mark it. ! 354: Then set n_times_set to -1 for the reg being set, so that ! 355: this reg will be considered invariant for subsequent insns. ! 356: We consider whether subsequent insns use the reg ! 357: in deciding whether it is worth actually moving. ! 358: ! 359: MAYBE_NEVER is nonzero if we have passed a conditional jump insn ! 360: and therefore it is possible that the insns we are scanning ! 361: would never be executed. At such times, we must make sure ! 362: that it is safe to execute the insn once instead of zero times. ! 363: When MAYBE_NEVER is 0, all insns will be executed at least once ! 364: so that is not a problem. */ ! 365: ! 366: p = scan_start; ! 367: while (1) ! 368: { ! 369: p = NEXT_INSN (p); ! 370: /* At end of a straight-in loop, we are done. ! 371: At end of a loop entered at the bottom, scan the top. */ ! 372: if (p == scan_start) ! 373: break; ! 374: if (p == end) ! 375: { ! 376: if (loop_top != 0) ! 377: p = NEXT_INSN (loop_top); ! 378: else ! 379: break; ! 380: if (p == scan_start) ! 381: break; ! 382: } ! 383: if (GET_CODE (p) == INSN ! 384: && GET_CODE (PATTERN (p)) == SET ! 385: && GET_CODE (SET_DEST (PATTERN (p))) == REG ! 386: && ! may_not_move[REGNO (SET_DEST (PATTERN (p)))]) ! 387: { ! 388: /* If this register is used or set outside the loop, ! 389: then we can move it only if we know this insn is ! 390: executed exactly once per iteration, ! 391: and we can check all the insns executed before it ! 392: to make sure none of them used the value that ! 393: was lying around at entry to the loop. */ ! 394: if ((uid_luid[regno_last_uid[REGNO (SET_DEST (PATTERN (p)))]] > INSN_LUID (end) ! 395: || uid_luid[regno_first_uid[REGNO (SET_DEST (PATTERN (p)))]] < INSN_LUID (loop_start)) ! 396: && (maybe_never ! 397: || loop_reg_used_before_p (p, loop_start, scan_start, end))) ! 398: ; ! 399: else if ((tem = invariant_p (SET_SRC (PATTERN (p)), n_times_set)) ! 400: && (n_times_set[REGNO (SET_DEST (PATTERN (p)))] == 1 ! 401: || consec_sets_invariant_p (SET_DEST (PATTERN (p)), ! 402: p, n_times_set)) ! 403: /* If the insn can cause a trap (such as divide by zero), ! 404: can't move it unless it's guaranteed to be executed ! 405: once loop is entered. Even a function call might ! 406: prevent the trap insn from being reached ! 407: (since it might exit!) */ ! 408: && ! ((maybe_never || call_passed) ! 409: && may_trap_p (SET_SRC (PATTERN (p))))) ! 410: { ! 411: register struct movable *m; ! 412: register int regno = REGNO (SET_DEST (PATTERN (p))); ! 413: int count; ! 414: m = (struct movable *) alloca (sizeof (struct movable)); ! 415: m->next = 0; ! 416: m->insn = p; ! 417: m->force = 0; ! 418: m->consec = n_times_set[REGNO (SET_DEST (PATTERN (p)))] - 1; ! 419: m->done = 0; ! 420: m->forces = 0; ! 421: m->partial = 0; ! 422: m->regno = regno; ! 423: m->cond = (tem > 1); ! 424: m->global = (uid_luid[regno_last_uid[regno]] > INSN_LUID (end) ! 425: || uid_luid[regno_first_uid[regno]] < INSN_LUID (loop_start)); ! 426: m->match = 0; ! 427: m->lifetime = (uid_luid[regno_last_uid[regno]] ! 428: - uid_luid[regno_first_uid[regno]]); ! 429: m->times_used = n_times_used[regno]; ! 430: n_times_set[regno] = -1; ! 431: /* Add M to the end of the chain MOVABLES. */ ! 432: if (movables == 0) ! 433: movables = m; ! 434: else ! 435: last_movable->next = m; ! 436: last_movable = m; ! 437: /* Skip the consecutive insns, if there are any. */ ! 438: for (count = m->consec - 1; count >= 0; count--) ! 439: { ! 440: do p = NEXT_INSN (p); ! 441: while (GET_CODE (p) == NOTE); ! 442: } ! 443: } ! 444: /* If this register is always set within a STRICT_LOW_PART ! 445: or set to zero, then its high bytes are constant. ! 446: So clear them outside the loop and within the loop ! 447: just load the low bytes. ! 448: We must check that the machine has an instruction to do so. ! 449: Also, if the value loaded into the register ! 450: depends on the same register, this cannot be done. */ ! 451: else if (SET_SRC (PATTERN (p)) == const0_rtx ! 452: && GET_CODE (NEXT_INSN (p)) == INSN ! 453: && GET_CODE (PATTERN (NEXT_INSN (p))) == SET ! 454: && (GET_CODE (SET_DEST (PATTERN (NEXT_INSN (p)))) ! 455: == STRICT_LOW_PART) ! 456: && (GET_CODE (XEXP (SET_DEST (PATTERN (NEXT_INSN (p))), 0)) ! 457: == SUBREG) ! 458: && (SUBREG_REG (XEXP (SET_DEST (PATTERN (NEXT_INSN (p))), 0)) ! 459: == SET_DEST (PATTERN (p))) ! 460: && !reg_mentioned_p (SET_DEST (PATTERN (p)), ! 461: SET_SRC (PATTERN (NEXT_INSN (p))))) ! 462: { ! 463: register int regno = REGNO (SET_DEST (PATTERN (p))); ! 464: if (n_times_set[regno] == 2) ! 465: { ! 466: register struct movable *m; ! 467: int count; ! 468: m = (struct movable *) alloca (sizeof (struct movable)); ! 469: m->next = 0; ! 470: m->insn = p; ! 471: m->force = 0; ! 472: m->consec = 0; ! 473: m->done = 0; ! 474: m->forces = 0; ! 475: m->partial = 1; ! 476: m->regno = regno; ! 477: m->cond = 0; ! 478: /* Say "global" so this register is not combined ! 479: with any other. In fact, it is sometimes possible ! 480: to combine two of these registers, but the criteria ! 481: are special and have not been programmed in. */ ! 482: m->global = 1; ! 483: m->match = 0; ! 484: m->lifetime = (uid_luid[regno_last_uid[regno]] ! 485: - uid_luid[regno_first_uid[regno]]); ! 486: m->times_used = n_times_used[regno]; ! 487: n_times_set[regno] = -1; ! 488: /* Add M to the end of the chain MOVABLES. */ ! 489: if (movables == 0) ! 490: movables = m; ! 491: else ! 492: last_movable->next = m; ! 493: last_movable = m; ! 494: /* Skip the consecutive insns, if there are any. */ ! 495: for (count = m->consec - 1; count >= 0; count--) ! 496: { ! 497: do p = NEXT_INSN (p); ! 498: while (GET_CODE (p) == NOTE); ! 499: } ! 500: } ! 501: } ! 502: } ! 503: /* Past a call insn, we get to insns which might not be executed ! 504: because the call might exit. This matters for insns that trap. */ ! 505: else if (GET_CODE (p) == CALL_INSN) ! 506: call_passed = 1; ! 507: /* Past a label or a jump, we get to insns for which we ! 508: can't count on whether or how many times they will be ! 509: executed during each iteration. Therefore, we can ! 510: only move out sets of trivial variables ! 511: (those not used after the loop). */ ! 512: else if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN) ! 513: maybe_never = 1; ! 514: } ! 515: ! 516: /* For each movable insn, see if the reg that it loads ! 517: leads when it dies right into another conditionally movable insn. ! 518: If so, record that the second insn "forces" the first one, ! 519: since the second can be moved only if the first is. */ ! 520: ! 521: { ! 522: register struct movable *m, *m1; ! 523: for (m1 = movables; m1; m1 = m1->next) ! 524: { ! 525: int regno = m1->regno; ! 526: for (m = m1->next; m; m = m->next) ! 527: if (INSN_UID (m->insn) == regno_last_uid[regno]) ! 528: break; ! 529: if (m != 0 && SET_SRC (PATTERN (m->insn)) == SET_DEST (PATTERN (m1->insn))) ! 530: m = 0; ! 531: ! 532: /* Increase the priority of the moving the first insn ! 533: since it permits the second to be moved as well. */ ! 534: if (m != 0) ! 535: { ! 536: m->forces = m1; ! 537: m1->lifetime += m->lifetime; ! 538: m1->times_used += m1->times_used; ! 539: } ! 540: } ! 541: } ! 542: ! 543: /* See if there are multiple movable insns that load the same value. ! 544: If there are, make all but the first point at the first one ! 545: through the `match' field, and add the priorities of them ! 546: all together as the priority of the first. */ ! 547: ! 548: { ! 549: register struct movable *m; ! 550: char *matched_regs = (char *) alloca (nregs); ! 551: ! 552: /* Regs that are used more than once are not allowed to match ! 553: or be matched. I'm no longer sure why not. */ ! 554: ! 555: for (m = movables; m; m = m->next) ! 556: if (m->match == 0 && n_times_used[m->regno] == 1) ! 557: { ! 558: register struct movable *m1; ! 559: int regno = m->regno; ! 560: ! 561: bzero (matched_regs, nregs); ! 562: matched_regs[regno] = 1; ! 563: ! 564: for (m1 = m->next; m1; m1 = m1->next) ! 565: if (m1->match == 0 && n_times_used[m1->regno] == 1 ! 566: /* A reg used outside the loop mustn't be eliminated. */ ! 567: && !m1->global ! 568: && (matched_regs[m1->regno] ! 569: || ! 570: ( ! 571: /* Can't combine regs with different modes ! 572: even if loaded from the same constant. */ ! 573: (GET_MODE (SET_DEST (PATTERN (m->insn))) ! 574: == GET_MODE (SET_DEST (PATTERN (m1->insn)))) ! 575: /* See if the source of M1 says it matches M. */ ! 576: && ((GET_CODE (SET_SRC (PATTERN (m1->insn))) == REG ! 577: && matched_regs[REGNO (SET_SRC (PATTERN (m1->insn)))]) ! 578: || rtx_equal_p (SET_SRC (PATTERN (m->insn)), ! 579: SET_SRC (PATTERN (m1->insn))) ! 580: || (REG_NOTES (m->insn) && REG_NOTES (m1->insn) ! 581: && REG_NOTE_KIND (REG_NOTES (m->insn)) == REG_EQUIV ! 582: && REG_NOTE_KIND (REG_NOTES (m1->insn)) == REG_EQUIV ! 583: && rtx_equal_p (XEXP (REG_NOTES (m->insn), 0), ! 584: XEXP (REG_NOTES (m1->insn), 0))))))) ! 585: { ! 586: m->lifetime += m1->lifetime; ! 587: m->times_used += m1->times_used; ! 588: m1->match = m; ! 589: matched_regs[m1->regno] = 1; ! 590: } ! 591: } ! 592: } ! 593: ! 594: /* Now consider each movable insn to decide whether it is worth moving. */ ! 595: ! 596: move_movables (movables, n_times_set, n_times_used, threshold, ! 597: insn_count, loop_start, end, nregs); ! 598: } ! 599: ! 600: /* Scan MOVABLES, and move the insns that deserve to be moved. ! 601: If two matching movables are combined, replace one reg with the ! 602: other throughout. */ ! 603: ! 604: static void ! 605: move_movables (movables, n_times_set, n_times_used, threshold, ! 606: insn_count, loop_start, end, nregs) ! 607: struct movable *movables; ! 608: short *n_times_set; ! 609: short *n_times_used; ! 610: int threshold; ! 611: int insn_count; ! 612: rtx loop_start; ! 613: rtx end; ! 614: int nregs; ! 615: { ! 616: rtx new_start = 0; ! 617: register struct movable *m; ! 618: register rtx p; ! 619: /* Map of pseudo-register replacements to handle combining ! 620: when we move several insns that load the same value ! 621: into different pseudo-registers. */ ! 622: rtx *reg_map = (rtx *) alloca (nregs * sizeof (rtx)); ! 623: char *already_moved = (char *) alloca (nregs); ! 624: ! 625: bzero (already_moved, nregs); ! 626: bzero (reg_map, nregs * sizeof (rtx)); ! 627: ! 628: for (m = movables; m; m = m->next) ! 629: { ! 630: /* Describe this movable insn. */ ! 631: ! 632: if (loop_dump_stream) ! 633: { ! 634: fprintf (loop_dump_stream, "Insn %d: regno %d (life %d), ", ! 635: INSN_UID (m->insn), m->regno, m->lifetime); ! 636: if (m->consec > 0) ! 637: fprintf (loop_dump_stream, "consec %d, ", m->consec); ! 638: if (m->cond) ! 639: fprintf (loop_dump_stream, "cond "); ! 640: if (m->force) ! 641: fprintf (loop_dump_stream, "force "); ! 642: if (m->global) ! 643: fprintf (loop_dump_stream, "global "); ! 644: if (m->done) ! 645: fprintf (loop_dump_stream, "done "); ! 646: if (m->match) ! 647: fprintf (loop_dump_stream, "matches %d ", ! 648: INSN_UID (m->match->insn)); ! 649: if (m->forces) ! 650: fprintf (loop_dump_stream, "forces %d ", ! 651: INSN_UID (m->forces->insn)); ! 652: } ! 653: ! 654: /* Ignore the insn if it's already done (it matched something else). ! 655: Otherwise, see if it is now safe to move. */ ! 656: ! 657: if (!m->done ! 658: && (! m->cond ! 659: || 1 == invariant_p (SET_SRC (PATTERN (m->insn)), n_times_set)) ! 660: && (! m->forces || m->forces->done)) ! 661: { ! 662: register int regno; ! 663: register rtx p; ! 664: int times_used = m->times_used + m->consec; ! 665: ! 666: /* We have an insn that is safe to move. ! 667: Compute its desirability. */ ! 668: ! 669: p = m->insn; ! 670: regno = m->regno; ! 671: ! 672: if (loop_dump_stream) ! 673: fprintf (loop_dump_stream, "reg uses %d ", times_used); ! 674: ! 675: /* An insn MUST be moved if we already moved something else ! 676: which is safe only if this one is moved too: that is, ! 677: if already_moved[REGNO] is nonzero. */ ! 678: ! 679: /* An insn is desirable to move if the new lifetime of the ! 680: register is no more than THRESHOLD times the old lifetime. ! 681: If it's not desirable, it means the loop is so big ! 682: that moving won't speed things up much, ! 683: and it is liable to make register usage worse. */ ! 684: ! 685: /* It is also desirable to move if it can be moved at no ! 686: extra cost because something else was already moved. */ ! 687: ! 688: if (already_moved[regno] ! 689: || (threshold * times_used * m->lifetime) >= insn_count ! 690: || (m->forces && m->forces->done ! 691: && n_times_used[m->forces->regno] == 1)) ! 692: { ! 693: int count; ! 694: register struct movable *m1; ! 695: ! 696: for (count = m->consec; count >= 0; count--) ! 697: { ! 698: rtx i1 = emit_insn_before (PATTERN (p), loop_start); ! 699: if (new_start == 0) ! 700: new_start = i1; ! 701: ! 702: if (loop_dump_stream) ! 703: fprintf (loop_dump_stream, "moved to %d", INSN_UID (i1)); ! 704: ! 705: /* Mark the moved, invariant reg as being equivalent to ! 706: its constant value. */ ! 707: REG_NOTES (i1) = REG_NOTES (p); ! 708: if (REG_NOTES (i1) == 0 ! 709: && ! m->partial /* But not if its a zero-extend clr. */ ! 710: && ! m->global /* and not if used outside the loop ! 711: (since it might get set outside). */ ! 712: && CONSTANT_P (SET_SRC (PATTERN (p)))) ! 713: REG_NOTES (i1) ! 714: = gen_rtx (EXPR_LIST, REG_EQUIV, ! 715: SET_SRC (PATTERN (p)), REG_NOTES (i1)); ! 716: delete_insn (p); ! 717: do p = NEXT_INSN (p); ! 718: while (GET_CODE (p) == NOTE); ! 719: ! 720: /* The more insns we move, the less we like moving them. */ ! 721: threshold -= 2; ! 722: } ! 723: ! 724: /* Any other movable that loads the same register ! 725: MUST be moved. */ ! 726: already_moved[regno] = 1; ! 727: ! 728: /* The reg set here is now invariant. */ ! 729: if (! m->partial) ! 730: n_times_set[regno] = 0; ! 731: ! 732: m->done = 1; ! 733: ! 734: /* Combine with this moved insn any other matching movables. */ ! 735: ! 736: for (m1 = m->next; m1; m1 = m1->next) ! 737: if (m1->match == m) ! 738: { ! 739: /* Schedule the reg loaded by M1 ! 740: for replacement so that shares the reg of M. */ ! 741: reg_map[m1->regno] = SET_DEST (PATTERN (m->insn)); ! 742: /* Get rid of the matching insn ! 743: and prevent further processing of it. */ ! 744: m1->done = 1; ! 745: delete_insn (m1->insn); ! 746: ! 747: /* Any other movable that loads the same register ! 748: MUST be moved. */ ! 749: already_moved[m1->regno] = 1; ! 750: ! 751: /* The reg merged here is now invariant. */ ! 752: if (m->partial) ! 753: n_times_set[m1->regno] = 0; ! 754: } ! 755: } ! 756: else if (loop_dump_stream) ! 757: fprintf (loop_dump_stream, "not desirable"); ! 758: } ! 759: else if (loop_dump_stream && !m->match) ! 760: fprintf (loop_dump_stream, "not safe"); ! 761: ! 762: if (loop_dump_stream) ! 763: fprintf (loop_dump_stream, "\n"); ! 764: } ! 765: ! 766: if (new_start == 0) ! 767: new_start = loop_start; ! 768: ! 769: /* Go through all the instructions in the loop, making ! 770: all the register substitutions scheduled in REG_MAP. */ ! 771: for (p = new_start; p != end; p = NEXT_INSN (p)) ! 772: if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN ! 773: || GET_CODE (p) == CALL_INSN) ! 774: replace_regs (PATTERN (p), reg_map); ! 775: } ! 776: ! 777: /* Optionally change a loop which enters just before the endtest ! 778: to one which falls straight in ! 779: after skipping around the entire loop if the endtest would drop out. ! 780: Returns 1 if the change was made, 0 if the loop was not really suitable. */ ! 781: ! 782: int ! 783: loop_skip_over (start, end, loop_entry_jump) ! 784: rtx start; ! 785: rtx end; ! 786: rtx loop_entry_jump; ! 787: { ! 788: rtx endtestjump; ! 789: register rtx p = JUMP_LABEL (loop_entry_jump); ! 790: ! 791: while (GET_CODE (p) != INSN && GET_CODE (p) != JUMP_INSN ! 792: && GET_CODE (p) != CALL_INSN) ! 793: p = NEXT_INSN (p); ! 794: endtestjump = next_real_insn (p); ! 795: ! 796: /* Check that we (1) enter at a compare insn and (2) ! 797: the insn (presumably a jump) following that compare ! 798: is the last in the loop and jumps back to the loop beginning. */ ! 799: ! 800: if (GET_CODE (PATTERN (p)) == SET ! 801: && SET_DEST (PATTERN (p)) == cc0_rtx ! 802: && endtestjump == prev_real_insn (end) ! 803: && prev_real_insn (JUMP_LABEL (endtestjump)) == loop_entry_jump) ! 804: { ! 805: rtx newlab; ! 806: /* This is the jump that we insert. */ ! 807: rtx new_jump; ! 808: ! 809: /* Ok, duplicate that test before start of loop. */ ! 810: emit_insn_before (copy_rtx (PATTERN (p)), start); ! 811: /* Make a new entry-jump (before the original one) ! 812: whose condition is opposite to the loop-around endtest ! 813: and which jumps around the loop (to just after the endtest). */ ! 814: newlab = gen_label_rtx (); ! 815: emit_label_after (newlab, endtestjump); ! 816: emit_jump_insn_before (copy_rtx (PATTERN (endtestjump)), start); ! 817: new_jump = PREV_INSN (start); ! 818: JUMP_LABEL (new_jump) = JUMP_LABEL (endtestjump); ! 819: LABEL_NUSES (JUMP_LABEL (endtestjump))++; ! 820: invert_jump (new_jump, newlab); ! 821: /* Delete the original entry-jump. */ ! 822: delete_insn (loop_entry_jump); ! 823: ! 824: return 1; ! 825: } ! 826: ! 827: return 0; ! 828: } ! 829: ! 830: /* Throughout the rtx X, replace many registers according to REG_MAP. ! 831: Return the replacement for X (which may be X with altered contents). ! 832: REG_MAP[R] is the replacement for register R, or 0 for don't replace. */ ! 833: ! 834: static rtx ! 835: replace_regs (x, reg_map) ! 836: rtx x; ! 837: rtx *reg_map; ! 838: { ! 839: register RTX_CODE code = GET_CODE (x); ! 840: register int i; ! 841: register char *fmt; ! 842: ! 843: switch (code) ! 844: { ! 845: case PC: ! 846: case CC0: ! 847: case CONST_INT: ! 848: case CONST_DOUBLE: ! 849: case CONST: ! 850: case SYMBOL_REF: ! 851: case LABEL_REF: ! 852: return x; ! 853: ! 854: case REG: ! 855: if (reg_map[REGNO (x)] != 0) ! 856: return reg_map[REGNO (x)]; ! 857: return x; ! 858: } ! 859: ! 860: fmt = GET_RTX_FORMAT (code); ! 861: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 862: { ! 863: if (fmt[i] == 'e') ! 864: XEXP (x, i) = replace_regs (XEXP (x, i), reg_map); ! 865: if (fmt[i] == 'E') ! 866: { ! 867: register int j; ! 868: for (j = 0; j < XVECLEN (x, i); j++) ! 869: XVECEXP (x, i, j) = replace_regs (XVECEXP (x, i, j), reg_map); ! 870: } ! 871: } ! 872: return x; ! 873: } ! 874: ! 875: /* P is an instruction that sets a register to the result of a ZERO_EXTEND. ! 876: Replace it with an instruction to load just the low bytes ! 877: if the machine supports such an instruction, ! 878: and insert above LOOP_START an instruction to clear the register. */ ! 879: ! 880: static void ! 881: constant_high_bytes (p, loop_start) ! 882: rtx p, loop_start; ! 883: { ! 884: register rtx new; ! 885: register int insn_code_number; ! 886: ! 887: /* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...))) ! 888: to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...). */ ! 889: ! 890: new = gen_rtx (SET, VOIDmode, ! 891: gen_rtx (STRICT_LOW_PART, VOIDmode, ! 892: gen_rtx (SUBREG, GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)), ! 893: SET_DEST (PATTERN (p)), ! 894: 0)), ! 895: XEXP (SET_SRC (PATTERN (p)), 0)); ! 896: insn_code_number = recog (new, p); ! 897: ! 898: if (insn_code_number) ! 899: { ! 900: register int i; ! 901: ! 902: /* Clear destination register before the loop. */ ! 903: emit_insn_before (gen_rtx (SET, VOIDmode, ! 904: SET_DEST (PATTERN (p)), ! 905: const0_rtx), ! 906: loop_start); ! 907: ! 908: /* Inside the loop, just load the low part. */ ! 909: PATTERN (p) = new; ! 910: } ! 911: } ! 912: ! 913: /* Verify that the ostensible loop starting at START ! 914: really is a loop: nothing jumps into it from outside. ! 915: Return the marker for the end of the loop, or zero if not a real loop. ! 916: ! 917: Also set the variables `unknown_*_altered' and `loop_has_call', ! 918: and fill in the array `loop_store_addrs'. */ ! 919: ! 920: static rtx ! 921: verify_loop (f, start) ! 922: rtx f, start; ! 923: { ! 924: register int level = 1; ! 925: register rtx insn, end; ! 926: ! 927: /* First find the LOOP_END that matches. ! 928: Also check each insn for storing in memory and record where. */ ! 929: ! 930: unknown_address_altered = 0; ! 931: unknown_aggregate_altered = 0; ! 932: fixed_aggregate_altered = 0; ! 933: loop_has_call = 0; ! 934: loop_store_addrs_idx = 0; ! 935: ! 936: for (insn = NEXT_INSN (start); level > 0; insn = NEXT_INSN (insn)) ! 937: { ! 938: if (insn == 0) ! 939: /* Parse errors can cause a loop-beg with no loop-end. */ ! 940: return 0; ! 941: if (GET_CODE (insn) == NOTE) ! 942: { ! 943: if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) ! 944: ++level; ! 945: else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) ! 946: { ! 947: --level; ! 948: if (level == 0) ! 949: { ! 950: end = insn; ! 951: break; ! 952: } ! 953: } ! 954: } ! 955: else if (GET_CODE (insn) == CALL_INSN) ! 956: { ! 957: unknown_address_altered = 1; ! 958: loop_has_call = 1; ! 959: } ! 960: else if (! unknown_address_altered) ! 961: { ! 962: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) ! 963: note_stores (PATTERN (insn), note_addr_stored); ! 964: } ! 965: } ! 966: ! 967: /* Now scan all jumps in the function and see if any of them can ! 968: reach a label within the range of the loop. */ ! 969: ! 970: for (insn = f; insn; insn = NEXT_INSN (insn)) ! 971: if (GET_CODE (insn) == JUMP_INSN ! 972: /* Don't get fooled by jumps inserted by loop-optimize. ! 973: They don't have valid LUIDs, and they never jump into loops. */ ! 974: && INSN_UID (insn) < max_uid ! 975: && (INSN_LUID (insn) < INSN_LUID (start) ! 976: || INSN_LUID (insn) > INSN_LUID (end)) ! 977: /* We have a jump that is outside the loop. ! 978: Does it jump into the loop? */ ! 979: && can_jump_into_range_p (PATTERN (insn), ! 980: INSN_LUID (start), INSN_LUID (end))) ! 981: return 0; ! 982: ! 983: #if 0 ! 984: /* Now scan all labels between them and check for any jumps from outside. ! 985: This uses the ref-chains set up by find_basic_blocks. ! 986: This code is not used because it's more convenient for other reasons ! 987: to do the loop optimization before find_basic_blocks. */ ! 988: ! 989: for (insn = start; insn != end; insn = NEXT_INSN (insn)) ! 990: if (GET_CODE (insn) == CODE_LABEL) ! 991: { ! 992: register rtx y; ! 993: for (y = LABEL_REFS (insn); y != insn; y = LABEL_NEXTREF (y)) ! 994: if (INSN_LUID (CONTAINING_INSN (y)) < INSN_LUID (start) ! 995: || INSN_LUID (CONTAINING_INSN (y)) > INSN_LUID (end)) ! 996: return 0; ! 997: } ! 998: #endif ! 999: ! 1000: return end; ! 1001: } ! 1002: ! 1003: /* Return 1 if somewhere in X is a LABEL_REF to a label ! 1004: located between BEG and END. */ ! 1005: ! 1006: static int ! 1007: can_jump_into_range_p (x, beg, end) ! 1008: rtx x; ! 1009: int beg, end; ! 1010: { ! 1011: register RTX_CODE code = GET_CODE (x); ! 1012: register int i; ! 1013: register char *fmt; ! 1014: ! 1015: if (code == LABEL_REF) ! 1016: { ! 1017: register int luid = INSN_LUID (XEXP (x, 0)); ! 1018: return luid > beg && luid < end; ! 1019: } ! 1020: ! 1021: fmt = GET_RTX_FORMAT (code); ! 1022: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 1023: { ! 1024: if (fmt[i] == 'e') ! 1025: { ! 1026: if (can_jump_into_range_p (XEXP (x, i), beg, end)) ! 1027: return 1; ! 1028: } ! 1029: else if (fmt[i] == 'E') ! 1030: { ! 1031: register int j; ! 1032: for (j = 0; j < XVECLEN (x, i); j++) ! 1033: if (can_jump_into_range_p (XVECEXP (x, i, j), beg, end)) ! 1034: return 1; ! 1035: } ! 1036: } ! 1037: ! 1038: return 0; ! 1039: } ! 1040: ! 1041: /* Record that a memory reference X is being set. */ ! 1042: ! 1043: static void ! 1044: note_addr_stored (x) ! 1045: rtx x; ! 1046: { ! 1047: rtx addr; ! 1048: if (x == 0 || GET_CODE (x) != MEM) ! 1049: return; ! 1050: if (GET_MODE (x) == BLKmode) ! 1051: unknown_address_altered = 1; ! 1052: else if (rtx_addr_varies_p (x)) ! 1053: { ! 1054: if (GET_CODE (XEXP (x, 0)) == PLUS) ! 1055: unknown_aggregate_altered = 1; ! 1056: else ! 1057: unknown_address_altered = 1; ! 1058: } ! 1059: else ! 1060: { ! 1061: register int i; ! 1062: register rtx addr = XEXP (x, 0); ! 1063: ! 1064: if (x->in_struct) ! 1065: fixed_aggregate_altered = 1; ! 1066: for (i = 0; i < loop_store_addrs_idx; i++) ! 1067: if (rtx_equal_p (loop_store_addrs[i], addr)) ! 1068: { ! 1069: if (loop_store_widths[i] < GET_MODE_SIZE (GET_MODE (x))) ! 1070: loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x)); ! 1071: break; ! 1072: } ! 1073: if (i == NUM_STORES) ! 1074: unknown_address_altered = 1; ! 1075: else if (i == loop_store_addrs_idx) ! 1076: { ! 1077: loop_store_widths[i] = GET_MODE_SIZE (GET_MODE (x)); ! 1078: loop_store_addrs[loop_store_addrs_idx++] = addr; ! 1079: } ! 1080: } ! 1081: } ! 1082: ! 1083: /* Return nonzero if the rtx X is invariant over the current loop. ! 1084: N_TIMES_SET is a vector whose element I is nonzero if register I ! 1085: is set during the loop. ! 1086: ! 1087: The value is 2 if we refer to something only conditionally invariant. ! 1088: ! 1089: If `unknown_address_altered' is nonzero, no memory ref is invariant. ! 1090: Otherwise if `unknown_aggregate_altered' is nonzero, ! 1091: a memory ref is invariant if it is not part of an aggregate ! 1092: and its address is fixed and not in `loop_store_addrs'. ! 1093: Otherwise if `fixed_aggregate_altered' is nonzero, ! 1094: a memory ref is invariant ! 1095: if its address is fixed and not in `loop_store_addrs'. ! 1096: Otherwise, a memory ref is invariant if its address is fixed and not in ! 1097: `loop_store_addrs' or if it is not an aggregate. */ ! 1098: ! 1099: static int ! 1100: invariant_p (x, n_times_set) ! 1101: register rtx x; ! 1102: short *n_times_set; ! 1103: { ! 1104: register int i; ! 1105: register RTX_CODE code = GET_CODE (x); ! 1106: register char *fmt; ! 1107: int conditional = 0; ! 1108: ! 1109: switch (code) ! 1110: { ! 1111: case CONST_INT: ! 1112: case CONST_DOUBLE: ! 1113: case SYMBOL_REF: ! 1114: case LABEL_REF: ! 1115: case CONST: ! 1116: return 1; ! 1117: ! 1118: case PC: ! 1119: case CC0: ! 1120: return 0; ! 1121: ! 1122: case REG: ! 1123: if (x == frame_pointer_rtx || x == arg_pointer_rtx ! 1124: || x->unchanging) ! 1125: return 1; ! 1126: if (n_times_set[REGNO (x)] == -1) ! 1127: return 2; ! 1128: return n_times_set[REGNO (x)] == 0; ! 1129: ! 1130: case MEM: ! 1131: /* A store in a varying-address scalar (or a subroutine call) ! 1132: could clobber anything in memory. */ ! 1133: if (unknown_address_altered) ! 1134: return 0; ! 1135: /* Don't mess with volatile memory references. */ ! 1136: if (x->volatil) ! 1137: return 0; ! 1138: /* If it's declared read-only, it is invariant ! 1139: if its address is invariant. */ ! 1140: if (x->unchanging) ! 1141: return invariant_p (XEXP (x, 0), n_times_set); ! 1142: /* A store in a varying-address aggregate component ! 1143: could clobber anything except a scalar with a fixed address. */ ! 1144: if (unknown_aggregate_altered ! 1145: && ((x->in_struct || GET_CODE (XEXP (x, 0)) == PLUS) ! 1146: || rtx_addr_varies_p (x))) ! 1147: return 0; ! 1148: /* A store in a fixed-address aggregate component ! 1149: could clobber anything whose address is not fixed, ! 1150: even an aggregate component. */ ! 1151: if (fixed_aggregate_altered ! 1152: && rtx_addr_varies_p (x)) ! 1153: return 0; ! 1154: /* Any store could clobber a varying-address scalar. */ ! 1155: if (loop_store_addrs_idx ! 1156: && !(x->in_struct || GET_CODE (XEXP (x, 0)) == PLUS) ! 1157: && rtx_addr_varies_p (x)) ! 1158: return 0; ! 1159: /* A store in a fixed address clobbers overlapping references. */ ! 1160: for (i = loop_store_addrs_idx - 1; i >= 0; i--) ! 1161: if (addr_overlap_p (x, loop_store_addrs[i], loop_store_widths[i])) ! 1162: return 0; ! 1163: /* It's not invalidated by a store in memory ! 1164: but we must still verify the address is invariant. */ ! 1165: break; ! 1166: ! 1167: case ASM_OPERANDS: ! 1168: /* Don't mess with insns declared volatile. */ ! 1169: if (x->volatil) ! 1170: return 0; ! 1171: } ! 1172: ! 1173: fmt = GET_RTX_FORMAT (code); ! 1174: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 1175: { ! 1176: if (fmt[i] == 'e') ! 1177: { ! 1178: int tem = invariant_p (XEXP (x, i), n_times_set); ! 1179: if (tem == 0) ! 1180: return 0; ! 1181: if (tem == 2) ! 1182: conditional = 1; ! 1183: } ! 1184: else if (fmt[i] == 'E') ! 1185: { ! 1186: register int j; ! 1187: for (j = 0; j < XVECLEN (x, i); j++) ! 1188: { ! 1189: int tem = invariant_p (XVECEXP (x, i, j), n_times_set); ! 1190: if (tem == 0) ! 1191: return 0; ! 1192: if (tem == 2) ! 1193: conditional = 1; ! 1194: } ! 1195: ! 1196: } ! 1197: } ! 1198: ! 1199: return 1 + conditional; ! 1200: } ! 1201: ! 1202: /* Return 1 if OTHER (a mem ref) overlaps the area of memory ! 1203: which is SIZE bytes starting at BASE. */ ! 1204: ! 1205: int ! 1206: addr_overlap_p (other, base, size) ! 1207: rtx other; ! 1208: rtx base; ! 1209: int size; ! 1210: { ! 1211: int start = 0, end; ! 1212: ! 1213: if (GET_CODE (base) == CONST) ! 1214: base = XEXP (base, 0); ! 1215: if (GET_CODE (base) == PLUS ! 1216: && GET_CODE (XEXP (base, 1)) == CONST_INT) ! 1217: { ! 1218: start = INTVAL (XEXP (base, 1)); ! 1219: base = XEXP (base, 0); ! 1220: } ! 1221: ! 1222: end = start + size; ! 1223: return refers_to_mem_p (other, base, start, end); ! 1224: } ! 1225: ! 1226: /* Return 1 if all the insns in the loop that set REG ! 1227: are INSN and the immediately following insns, ! 1228: and if each of those insns sets REG in an invariant way ! 1229: according to TABLE (not counting uses of REG in them). ! 1230: ! 1231: We assume that INSN itself is the first set of REG ! 1232: and that its source is invariant. */ ! 1233: ! 1234: static int ! 1235: consec_sets_invariant_p (reg, insn, table) ! 1236: rtx reg, insn; ! 1237: short *table; ! 1238: { ! 1239: register rtx p = insn; ! 1240: register int regno = REGNO (reg); ! 1241: /* Number of sets we have to insist on finding after INSN. */ ! 1242: int count = table[regno] - 1; ! 1243: int old = table[regno]; ! 1244: ! 1245: table[regno] = 0; ! 1246: ! 1247: while (count > 0) ! 1248: { ! 1249: register enum rtx_code code; ! 1250: p = NEXT_INSN (p); ! 1251: code = GET_CODE (p); ! 1252: if (code == INSN && GET_CODE (PATTERN (p)) == SET ! 1253: && GET_CODE (SET_DEST (PATTERN (p))) == REG ! 1254: && REGNO (SET_DEST (PATTERN (p))) == regno ! 1255: && invariant_p (SET_SRC (PATTERN (p)), table)) ! 1256: count--; ! 1257: else if (code != NOTE) ! 1258: { ! 1259: table[regno] = old; ! 1260: return 0; ! 1261: } ! 1262: } ! 1263: ! 1264: table[regno] = old; ! 1265: return 1; ! 1266: } ! 1267: ! 1268: #if 0 ! 1269: /* I don't think this condition is sufficient to allow INSN ! 1270: to be moved, so we no longer test it. */ ! 1271: ! 1272: /* Return 1 if all insns in the basic block of INSN and following INSN ! 1273: that set REG are invariant according to TABLE. */ ! 1274: ! 1275: static int ! 1276: all_sets_invariant_p (reg, insn, table) ! 1277: rtx reg, insn; ! 1278: short *table; ! 1279: { ! 1280: register rtx p = insn; ! 1281: register int regno = REGNO (reg); ! 1282: ! 1283: while (1) ! 1284: { ! 1285: register enum rtx_code code; ! 1286: p = NEXT_INSN (p); ! 1287: code = GET_CODE (p); ! 1288: if (code == CODE_LABEL || code == JUMP_INSN) ! 1289: return 1; ! 1290: if (code == INSN && GET_CODE (PATTERN (p)) == SET ! 1291: && GET_CODE (SET_DEST (PATTERN (p))) == REG ! 1292: && REGNO (SET_DEST (PATTERN (p))) == regno) ! 1293: { ! 1294: if (!invariant_p (SET_SRC (PATTERN (p)), table)) ! 1295: return 0; ! 1296: } ! 1297: } ! 1298: } ! 1299: #endif /* 0 */ ! 1300: ! 1301: /* Increment N_TIMES_SET at the index of each register ! 1302: that is modified by an insn between FROM and TO. ! 1303: If the value of an element of N_TIMES_SET becomes 2 or more, ! 1304: do not keep incrementing it; all values >= 2 would be ! 1305: equivalent anyway, and this way we avoid danger of overflow. ! 1306: ! 1307: Store in *COUNT_PTR the number of actual instruction ! 1308: in the loop. We use this to decide what is worth moving out. */ ! 1309: ! 1310: /* last_set[n] is nonzero iff reg n has been set in the current basic block. ! 1311: In that case, it is the insn that last set reg n. */ ! 1312: ! 1313: static void ! 1314: count_loop_regs_set (from, to, n_times_set, may_not_move, count_ptr, nregs) ! 1315: register rtx from, to; ! 1316: short *n_times_set; ! 1317: char *may_not_move; ! 1318: int *count_ptr; ! 1319: int nregs; ! 1320: { ! 1321: register rtx *last_set = (rtx *) alloca (nregs * sizeof (rtx)); ! 1322: register rtx insn; ! 1323: register int count = 0; ! 1324: register rtx dest; ! 1325: ! 1326: bzero (last_set, nregs * sizeof (rtx)); ! 1327: for (insn = from; insn != to; insn = NEXT_INSN (insn)) ! 1328: { ! 1329: if (GET_CODE (insn) == CALL_INSN) ! 1330: { ! 1331: /* If a register is used as a subroutine address, ! 1332: don't allow this register's setting to be moved out of the loop. ! 1333: This condition is not at all logically correct ! 1334: but it averts a very common lossage pattern ! 1335: and creates lossage much less often. */ ! 1336: if (GET_CODE (PATTERN (insn)) == CALL ! 1337: && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM ! 1338: && GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == REG) ! 1339: { ! 1340: register int regno ! 1341: = REGNO (XEXP (XEXP (PATTERN (insn), 0), 0)); ! 1342: may_not_move[regno] = 1; ! 1343: } ! 1344: else if (GET_CODE (PATTERN (insn)) == SET ! 1345: && GET_CODE (SET_SRC (PATTERN (insn))) == CALL ! 1346: && GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0)) == MEM ! 1347: && GET_CODE (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)) == REG) ! 1348: { ! 1349: register int regno ! 1350: = REGNO (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0)); ! 1351: may_not_move[regno] = 1; ! 1352: /* The call insn itself sets a reg, which cannot be moved. */ ! 1353: may_not_move[REGNO (SET_DEST (PATTERN (insn)))] = 1; ! 1354: n_times_set[REGNO (SET_DEST (PATTERN (insn)))]++; ! 1355: } ! 1356: } ! 1357: if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) ! 1358: { ! 1359: ++count; ! 1360: if (GET_CODE (PATTERN (insn)) == CLOBBER ! 1361: && GET_CODE (XEXP (PATTERN (insn), 0)) == REG) ! 1362: /* Don't move a reg that has an explicit clobber. ! 1363: We might do so sometimes, but it's not worth the pain. */ ! 1364: may_not_move[REGNO (XEXP (PATTERN (insn), 0))] = 1; ! 1365: else if (GET_CODE (PATTERN (insn)) == SET) ! 1366: { ! 1367: dest = SET_DEST (PATTERN (insn)); ! 1368: while (GET_CODE (dest) == SUBREG ! 1369: || GET_CODE (dest) == ZERO_EXTRACT ! 1370: || GET_CODE (dest) == SIGN_EXTRACT ! 1371: || GET_CODE (dest) == STRICT_LOW_PART) ! 1372: dest = XEXP (dest, 0); ! 1373: if (GET_CODE (dest) == REG) ! 1374: { ! 1375: register int regno = REGNO (dest); ! 1376: /* If this is the first setting of this reg ! 1377: in current basic block, and it was set before, ! 1378: it must be set in two basic blocks, so it cannot ! 1379: be moved out of the loop. */ ! 1380: if (n_times_set[regno] > 0 && last_set[regno] == 0) ! 1381: may_not_move[regno] = 1; ! 1382: /* If this is not first setting in current basic block, ! 1383: see if reg was used in between previous one and this. ! 1384: If so, neither one can be moved. */ ! 1385: if (last_set[regno] != 0 ! 1386: && reg_used_between_p (dest, last_set[regno], insn)) ! 1387: may_not_move[regno] = 1; ! 1388: ++n_times_set[regno]; ! 1389: last_set[regno] = insn; ! 1390: } ! 1391: } ! 1392: else if (GET_CODE (PATTERN (insn)) == PARALLEL) ! 1393: { ! 1394: register int i; ! 1395: for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--) ! 1396: { ! 1397: register rtx x = XVECEXP (PATTERN (insn), 0, i); ! 1398: if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG) ! 1399: /* Don't move a reg that has an explicit clobber. ! 1400: It's not worth the pain to try to do it correctly. */ ! 1401: may_not_move[REGNO (XEXP (x, 0))] = 1; ! 1402: if (GET_CODE (x) == SET) ! 1403: { ! 1404: dest = SET_DEST (x); ! 1405: while (GET_CODE (dest) == SUBREG ! 1406: || GET_CODE (dest) == ZERO_EXTRACT ! 1407: || GET_CODE (dest) == SIGN_EXTRACT ! 1408: || GET_CODE (dest) == STRICT_LOW_PART) ! 1409: dest = XEXP (dest, 0); ! 1410: if (GET_CODE (dest) == REG) ! 1411: { ! 1412: register int regno = REGNO (dest); ! 1413: ++n_times_set[regno]; ! 1414: may_not_move[regno] = 1; ! 1415: last_set[regno] = insn; ! 1416: } ! 1417: } ! 1418: } ! 1419: } ! 1420: } ! 1421: if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN) ! 1422: bzero (last_set, nregs * sizeof (rtx)); ! 1423: } ! 1424: *count_ptr = count; ! 1425: } ! 1426: ! 1427: /* Given a loop that is bounded by LOOP_START and LOOP_END ! 1428: and that is entered at SCAN_START, ! 1429: return 1 if the register set by insn INSN is used by ! 1430: any insn that precedes INSN in cyclic order starting ! 1431: from the loop entry point. */ ! 1432: ! 1433: static int ! 1434: loop_reg_used_before_p (insn, loop_start, scan_start, loop_end) ! 1435: rtx insn, loop_start, scan_start, loop_end; ! 1436: { ! 1437: rtx reg = SET_DEST (PATTERN (insn)); ! 1438: if (INSN_LUID (scan_start) > INSN_LUID (insn)) ! 1439: return (reg_used_between_p (reg, scan_start, loop_end) ! 1440: || reg_used_between_p (reg, loop_start, insn)); ! 1441: else ! 1442: return reg_used_between_p (reg, scan_start, insn); ! 1443: } ! 1444: ! 1445: /* Return nonzero if evaluating rtx X might cause a trap. */ ! 1446: ! 1447: static int ! 1448: may_trap_p (x) ! 1449: rtx x; ! 1450: { ! 1451: int i; ! 1452: enum rtx_code code = GET_CODE (x); ! 1453: char *fmt; ! 1454: ! 1455: switch (code) ! 1456: { ! 1457: /* Handle these cases fast. */ ! 1458: case CONST_INT: ! 1459: case CONST_DOUBLE: ! 1460: case SYMBOL_REF: ! 1461: case LABEL_REF: ! 1462: case CONST: ! 1463: case PC: ! 1464: case CC0: ! 1465: case REG: ! 1466: return 0; ! 1467: ! 1468: /* Division by a non-constant might trap. */ ! 1469: case DIV: ! 1470: case MOD: ! 1471: case UDIV: ! 1472: case UMOD: ! 1473: if (! CONSTANT_P (XEXP (x, 1)) ! 1474: && GET_CODE (XEXP (x, 1)) != CONST_DOUBLE) ! 1475: return 1; ! 1476: break; ! 1477: ! 1478: /* Memory ref can trap unless it's a static var or a stack slot. */ ! 1479: case MEM: ! 1480: return rtx_varies_p (XEXP (x, 0)); ! 1481: } ! 1482: ! 1483: fmt = GET_RTX_FORMAT (code); ! 1484: for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) ! 1485: { ! 1486: if (fmt[i] == 'e') ! 1487: { ! 1488: if (may_trap_p (XEXP (x, i))) ! 1489: return 1; ! 1490: } ! 1491: else if (fmt[i] == 'E') ! 1492: { ! 1493: register int j; ! 1494: for (j = 0; j < XVECLEN (x, i); j++) ! 1495: if (may_trap_p (XVECEXP (x, i, j))) ! 1496: return 1; ! 1497: } ! 1498: } ! 1499: return 0; ! 1500: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.