?? loop.c
字號:
/* The reg set here is now invariant. */ if (! m->partial) n_times_set[regno] = 0; m->done = 1; /* Change the length-of-life info for the register to say it lives at least the full length of this loop. This will help guide optimizations in outer loops. */ if (uid_luid[regno_first_uid[regno]] > INSN_LUID (loop_start)) /* This is the old insn before all the moved insns. We can't use the moved insn because it is out of range in uid_luid. Only the old insns have luids. */ regno_first_uid[regno] = INSN_UID (loop_start); if (uid_luid[regno_last_uid[regno]] < INSN_LUID (end)) regno_last_uid[regno] = INSN_UID (end); /* Combine with this moved insn any other matching movables. */ for (m1 = m->next; m1; m1 = m1->next) if (m1->match == m) { rtx temp; /* Schedule the reg loaded by M1 for replacement so that shares the reg of M. */ reg_map[m1->regno] = SET_DEST (PATTERN (m->insn)); /* Get rid of the matching insn and prevent further processing of it. */ m1->done = 1; /* if library call, delete all insn except last, which is deleted below */ if (temp = find_reg_note (m1->insn, REG_RETVAL, 0)) { for (temp = XEXP (temp, 0); temp != m1->insn; temp = NEXT_INSN (temp)) delete_insn (temp); } delete_insn (m1->insn); /* Any other movable that loads the same register MUST be moved. */ already_moved[m1->regno] = 1; /* The reg merged here is now invariant, if the reg it matches is invariant. */ if (! m->partial) n_times_set[m1->regno] = 0; } } else if (loop_dump_stream) fprintf (loop_dump_stream, "not desirable"); } else if (loop_dump_stream && !m->match) fprintf (loop_dump_stream, "not safe"); if (loop_dump_stream) fprintf (loop_dump_stream, "\n"); } if (new_start == 0) new_start = loop_start; /* Go through all the instructions in the loop, making all the register substitutions scheduled in REG_MAP. */ for (p = new_start; p != end; p = NEXT_INSN (p)) if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN || GET_CODE (p) == CALL_INSN) { rtx tail; replace_regs (PATTERN (p), reg_map, nregs); /* Subsitute registers in the equivalent expression also. */ for (tail = REG_NOTES (p); tail; tail = XEXP (tail, 1)) if (REG_NOTE_KIND (tail) == REG_EQUAL || REG_NOTE_KIND (tail) == REG_EQUIV) replace_regs (XEXP (tail, 0), reg_map, nregs); }}/* Optionally change a loop which enters just before the endtest to one which falls straight in after skipping around the entire loop if the endtest would drop out. Returns 1 if the change was made, 0 if the loop was not really suitable. */intloop_skip_over (start, end, loop_entry_jump) rtx start; rtx end; rtx loop_entry_jump;{ rtx entry_insn; rtx endtest; rtx endtestjump; register rtx p = JUMP_LABEL (loop_entry_jump); while (GET_CODE (p) != INSN && GET_CODE (p) != JUMP_INSN && GET_CODE (p) != CALL_INSN) p = NEXT_INSN (p); entry_insn = p; /* Skip any ordinary arithmetic insns to find the compare. */ for (; p != 0; p = NEXT_INSN (p)) if (GET_CODE (p) != NOTE) if (GET_CODE (p) != INSN || sets_cc0_p (PATTERN (p))) break; if (p == 0 || GET_CODE (p) != INSN) return 0; endtest = p; endtestjump = next_real_insn (p); /* Check that (1) we have reached a compare insn and (2) the insn (presumably a jump) following that compare is the last in the loop and jumps back to the loop beginning. */ if (sets_cc0_p (PATTERN (endtest)) > 0 && endtestjump == prev_real_insn (end) && prev_real_insn (JUMP_LABEL (endtestjump)) == loop_entry_jump) { rtx newlab; /* This is the jump that we insert. */ rtx new_jump; /* Duplicate the ordinary arith insns before the compare. */ for (p = entry_insn; p != endtest; p = NEXT_INSN (p)) if (GET_CODE (p) == INSN) { rtx new = emit_insn_before (copy_rtx (PATTERN (p)), start); if (REG_NOTES (p)) REG_NOTES (new) = copy_rtx (REG_NOTES (p)); } /* Ok, duplicate that test before start of loop. */ emit_insn_before (copy_rtx (PATTERN (endtest)), start); /* Make a new entry-jump (before the original one) whose condition is opposite to the loop-around endtest and which jumps around the loop (to just after the ending NOTE). */ newlab = gen_label_rtx (); emit_label_after (newlab, end); emit_jump_insn_before (copy_rtx (PATTERN (endtestjump)), start); new_jump = PREV_INSN (start); JUMP_LABEL (new_jump) = JUMP_LABEL (endtestjump); LABEL_NUSES (JUMP_LABEL (endtestjump))++; invert_jump (new_jump, newlab); /* Delete the original entry-jump. */ delete_insn (loop_entry_jump); return 1; } return 0;}/* Throughout the rtx X, replace many registers according to REG_MAP. Return the replacement for X (which may be X with altered contents). REG_MAP[R] is the replacement for register R, or 0 for don't replace. NREGS is the length of REG_MAP; regs >= NREGS are not mapped. */static rtxreplace_regs (x, reg_map, nregs) rtx x; rtx *reg_map; int nregs;{ register enum rtx_code code; register int i; register char *fmt; if (x == 0) return x; code = GET_CODE (x); switch (code) { case PC: case CC0: case CONST_INT: case CONST_DOUBLE: case CONST: case SYMBOL_REF: case LABEL_REF: return x; case REG: /* Verify that the register has an entry before trying to access it. */ if (REGNO (x) < nregs && reg_map[REGNO (x)] != 0) return reg_map[REGNO (x)]; return x; } fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') XEXP (x, i) = replace_regs (XEXP (x, i), reg_map, nregs); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) XVECEXP (x, i, j) = replace_regs (XVECEXP (x, i, j), reg_map, nregs); } } return x;}/* Scan X and replace the address of any MEM in it with ADDR. REG is the address that MEM should have before the replacement. */static voidreplace_call_address (x, reg, addr) rtx x, reg, addr;{ register enum rtx_code code; register int i; register char *fmt; if (x == 0) return; code = GET_CODE (x); switch (code) { case PC: case CC0: case CONST_INT: case CONST_DOUBLE: case CONST: case SYMBOL_REF: case LABEL_REF: case REG: return; case SET: /* Short cut for very common case. */ replace_call_address (XEXP (x, 1), reg, addr); return; case CALL: /* Short cut for very common case. */ replace_call_address (XEXP (x, 0), reg, addr); return; case MEM: /* If this MEM uses a reg other than the one we expected, something is wrong. */ if (XEXP (x, 0) != reg) abort (); XEXP (x, 0) = addr; return; } fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') replace_call_address (XEXP (x, i), reg, addr); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) replace_call_address (XVECEXP (x, i, j), reg, addr); } }}/* Return the number of memory refs to addresses that vary in the rtx X. */static intcount_nonfixed_reads (x) rtx x;{ register enum rtx_code code; register int i; register char *fmt; int value; if (x == 0) return 0; code = GET_CODE (x); switch (code) { case PC: case CC0: case CONST_INT: case CONST_DOUBLE: case CONST: case SYMBOL_REF: case LABEL_REF: case REG: return 0; case MEM: return rtx_varies_p (XEXP (x, 0)) + count_nonfixed_reads (XEXP (x, 0)); } value = 0; fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') value += count_nonfixed_reads (XEXP (x, i)); if (fmt[i] == 'E') { register int j; for (j = 0; j < XVECLEN (x, i); j++) value += count_nonfixed_reads (XVECEXP (x, i, j)); } } return value;}#if 0/* P is an instruction that sets a register to the result of a ZERO_EXTEND. Replace it with an instruction to load just the low bytes if the machine supports such an instruction, and insert above LOOP_START an instruction to clear the register. */static voidconstant_high_bytes (p, loop_start) rtx p, loop_start;{ register rtx new; register int insn_code_number; /* Try to change (SET (REG ...) (ZERO_EXTEND (..:B ...))) to (SET (STRICT_LOW_PART (SUBREG:B (REG...))) ...). */ new = gen_rtx (SET, VOIDmode, gen_rtx (STRICT_LOW_PART, VOIDmode, gen_rtx (SUBREG, GET_MODE (XEXP (SET_SRC (PATTERN (p)), 0)), SET_DEST (PATTERN (p)), 0)), XEXP (SET_SRC (PATTERN (p)), 0)); insn_code_number = recog (new, p); if (insn_code_number) { register int i; /* Clear destination register before the loop. */ emit_insn_before (gen_rtx (SET, VOIDmode, SET_DEST (PATTERN (p)), const0_rtx), loop_start); /* Inside the loop, just load the low part. */ PATTERN (p) = new; }}#endif/* Verify that the ostensible loop starting at START really is a loop: nothing jumps into it from outside. Return the marker for the end of the loop, or zero if not a real loop. Also set the variables `unknown_*_altered', `loop_has_call', and `loop_has_volatile' and fill in the array `loop_store_addrs'. */static rtxverify_loop (f, start) rtx f, start;{ register int level = 1; register rtx insn, end; /* First find the LOOP_END that matches. Also check each insn for storing in memory and record where. */ unknown_address_altered = 0; unknown_aggregate_altered = 0; fixed_aggregate_altered = 0; loop_has_call = 0; loop_has_volatile = 0; loop_store_addrs_idx = 0; num_mem_sets = 0; loops_enclosed = 1; loop_continue = 0; for (insn = NEXT_INSN (start); level > 0; insn = NEXT_INSN (insn)) { if (insn == 0) /* Parse errors can cause a loop-beg with no loop-end. */ return 0; if (GET_CODE (insn) == NOTE) { if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) { ++level; /* Count number of loops contained in this one. */ loops_enclosed++; } else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) { --level; if (level == 0) { end = insn; break; } } else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_CONT) { if (level == 1) loop_continue = insn; } /* Don't optimize loops containing setjmps. On some machines, longjmp does not restore the reg values as of the time of the setjmp. */ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP) return 0; } else if (GET_CODE (insn) == CALL_INSN) { unknown_address_altered = 1; loop_has_call = 1; }/* ??? else if (! unknown_address_altered) */ else { if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN) { if (volatile_refs_p (PATTERN (insn))) loop_has_volatile = 1; note_stores (PATTERN (insn), note_addr_stored); } } } /* Now scan all jumps in the function and see if any of them can reach a label within the range of the loop. */ for (insn = f; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == JUMP_INSN /* Don't get fooled by jumps inserted by loop-optimize.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -