diff options
author | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-02-05 16:34:02 +0000 |
---|---|---|
committer | amylaar <amylaar@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-02-05 16:34:02 +0000 |
commit | 97bcb74ea3328edb61829a090751e7a44d5277e3 (patch) | |
tree | d53fdc7c09c775cf4675b87dab49d13457f60606 /gcc/local-alloc.c | |
parent | aa2f2b42fc26405f52450a218676ab98383dd54c (diff) | |
download | gcc-97bcb74ea3328edb61829a090751e7a44d5277e3.tar.gz |
* regmove.c: Update.
* flags.h (flag_regmove): Declare.
* rtl.h (optimize_reg_copy_1, optimize_reg_copy_2): Don't declare.
* local-alloc.c (optimize_reg_copy_1, optimize_reg_copy_2):
Moved into regmove; changed caller.
* toplev.c (rest_of_compilation): Call regmove_optimize also for
expensive_optimizations.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@17669 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/local-alloc.c')
-rw-r--r-- | gcc/local-alloc.c | 279 |
1 files changed, 1 insertions, 278 deletions
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index 62f3e171895..dc8357c6894 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -739,268 +739,6 @@ memref_used_between_p (memref, start, end) return 0; } -/* INSN is a copy from SRC to DEST, both registers, and SRC does not die - in INSN. - - Search forward to see if SRC dies before either it or DEST is modified, - but don't scan past the end of a basic block. If so, we can replace SRC - with DEST and let SRC die in INSN. - - This will reduce the number of registers live in that range and may enable - DEST to be tied to SRC, thus often saving one register in addition to a - register-register copy. */ - -int -optimize_reg_copy_1 (insn, dest, src) - rtx insn; - rtx dest; - rtx src; -{ - rtx p, q; - rtx note; - rtx dest_death = 0; - int sregno = REGNO (src); - int dregno = REGNO (dest); - - if (sregno == dregno - /* We don't want to mess with hard regs if register classes are small. */ - || (SMALL_REGISTER_CLASSES - && (sregno < FIRST_PSEUDO_REGISTER - || dregno < FIRST_PSEUDO_REGISTER)) - /* We don't see all updates to SP if they are in an auto-inc memory - reference, so we must disallow this optimization on them. */ - || sregno == STACK_POINTER_REGNUM || dregno == STACK_POINTER_REGNUM) - return 0; - - for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) - { - if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN - || (GET_CODE (p) == NOTE - && (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG - || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END))) - break; - - if (GET_RTX_CLASS (GET_CODE (p)) != 'i') - continue; - - if (reg_set_p (src, p) || reg_set_p (dest, p) - /* Don't change a USE of a register. */ - || (GET_CODE (PATTERN (p)) == USE - && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0)))) - break; - - /* See if all of SRC dies in P. This test is slightly more - conservative than it needs to be. */ - if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0 - && GET_MODE (XEXP (note, 0)) == GET_MODE (src)) - { - int failed = 0; - int length = 0; - int d_length = 0; - int n_calls = 0; - int d_n_calls = 0; - - /* We can do the optimization. Scan forward from INSN again, - replacing regs as we go. Set FAILED if a replacement can't - be done. In that case, we can't move the death note for SRC. - This should be rare. */ - - /* Set to stop at next insn. */ - for (q = next_real_insn (insn); - q != next_real_insn (p); - q = next_real_insn (q)) - { - if (reg_overlap_mentioned_p (src, PATTERN (q))) - { - /* If SRC is a hard register, we might miss some - overlapping registers with validate_replace_rtx, - so we would have to undo it. We can't if DEST is - present in the insn, so fail in that combination - of cases. */ - if (sregno < FIRST_PSEUDO_REGISTER - && reg_mentioned_p (dest, PATTERN (q))) - failed = 1; - - /* Replace all uses and make sure that the register - isn't still present. */ - else if (validate_replace_rtx (src, dest, q) - && (sregno >= FIRST_PSEUDO_REGISTER - || ! reg_overlap_mentioned_p (src, - PATTERN (q)))) - { - /* We assume that a register is used exactly once per - insn in the updates below. If this is not correct, - no great harm is done. */ - if (sregno >= FIRST_PSEUDO_REGISTER) - REG_N_REFS (sregno) -= loop_depth; - if (dregno >= FIRST_PSEUDO_REGISTER) - REG_N_REFS (dregno) += loop_depth; - } - else - { - validate_replace_rtx (dest, src, q); - failed = 1; - } - } - - /* Count the insns and CALL_INSNs passed. If we passed the - death note of DEST, show increased live length. */ - length++; - if (dest_death) - d_length++; - - /* If the insn in which SRC dies is a CALL_INSN, don't count it - as a call that has been crossed. Otherwise, count it. */ - if (q != p && GET_CODE (q) == CALL_INSN) - { - n_calls++; - if (dest_death) - d_n_calls++; - } - - /* If DEST dies here, remove the death note and save it for - later. Make sure ALL of DEST dies here; again, this is - overly conservative. */ - if (dest_death == 0 - && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0) - { - if (GET_MODE (XEXP (dest_death, 0)) != GET_MODE (dest)) - failed = 1, dest_death = 0; - else - remove_note (q, dest_death); - } - } - - if (! failed) - { - if (sregno >= FIRST_PSEUDO_REGISTER) - { - if (REG_LIVE_LENGTH (sregno) >= 0) - { - REG_LIVE_LENGTH (sregno) -= length; - /* REG_LIVE_LENGTH is only an approximation after - combine if sched is not run, so make sure that we - still have a reasonable value. */ - if (REG_LIVE_LENGTH (sregno) < 2) - REG_LIVE_LENGTH (sregno) = 2; - } - - REG_N_CALLS_CROSSED (sregno) -= n_calls; - } - - if (dregno >= FIRST_PSEUDO_REGISTER) - { - if (REG_LIVE_LENGTH (dregno) >= 0) - REG_LIVE_LENGTH (dregno) += d_length; - - REG_N_CALLS_CROSSED (dregno) += d_n_calls; - } - - /* Move death note of SRC from P to INSN. */ - remove_note (p, note); - XEXP (note, 1) = REG_NOTES (insn); - REG_NOTES (insn) = note; - } - - /* Put death note of DEST on P if we saw it die. */ - if (dest_death) - { - XEXP (dest_death, 1) = REG_NOTES (p); - REG_NOTES (p) = dest_death; - } - - return ! failed; - } - - /* If SRC is a hard register which is set or killed in some other - way, we can't do this optimization. */ - else if (sregno < FIRST_PSEUDO_REGISTER - && dead_or_set_p (p, src)) - break; - } - return 0; -} - -/* INSN is a copy of SRC to DEST, in which SRC dies. See if we now have - a sequence of insns that modify DEST followed by an insn that sets - SRC to DEST in which DEST dies, with no prior modification of DEST. - (There is no need to check if the insns in between actually modify - DEST. We should not have cases where DEST is not modified, but - the optimization is safe if no such modification is detected.) - In that case, we can replace all uses of DEST, starting with INSN and - ending with the set of SRC to DEST, with SRC. We do not do this - optimization if a CALL_INSN is crossed unless SRC already crosses a - call or if DEST dies before the copy back to SRC. - - It is assumed that DEST and SRC are pseudos; it is too complicated to do - this for hard registers since the substitutions we may make might fail. */ - -void -optimize_reg_copy_2 (insn, dest, src) - rtx insn; - rtx dest; - rtx src; -{ - rtx p, q; - rtx set; - int sregno = REGNO (src); - int dregno = REGNO (dest); - - for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) - { - if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN - || (GET_CODE (p) == NOTE - && (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG - || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END))) - break; - - if (GET_RTX_CLASS (GET_CODE (p)) != 'i') - continue; - - set = single_set (p); - if (set && SET_SRC (set) == dest && SET_DEST (set) == src - && find_reg_note (p, REG_DEAD, dest)) - { - /* We can do the optimization. Scan forward from INSN again, - replacing regs as we go. */ - - /* Set to stop at next insn. */ - for (q = insn; q != NEXT_INSN (p); q = NEXT_INSN (q)) - if (GET_RTX_CLASS (GET_CODE (q)) == 'i') - { - if (reg_mentioned_p (dest, PATTERN (q))) - { - PATTERN (q) = replace_rtx (PATTERN (q), dest, src); - - /* We assume that a register is used exactly once per - insn in the updates below. If this is not correct, - no great harm is done. */ - REG_N_REFS (dregno) -= loop_depth; - REG_N_REFS (sregno) += loop_depth; - } - - - if (GET_CODE (q) == CALL_INSN) - { - REG_N_CALLS_CROSSED (dregno)--; - REG_N_CALLS_CROSSED (sregno)++; - } - } - - remove_note (p, find_reg_note (p, REG_DEAD, dest)); - REG_N_DEATHS (dregno)--; - remove_note (insn, find_reg_note (insn, REG_DEAD, src)); - REG_N_DEATHS (sregno)--; - return; - } - - if (reg_set_p (src, p) - || find_reg_note (p, REG_DEAD, dest) - || (GET_CODE (p) == CALL_INSN && REG_N_CALLS_CROSSED (sregno) == 0)) - break; - } -} - /* Find registers that are equivalent to a single value throughout the compilation (either because they can be referenced in memory or are set once from a single constant). Lower their priority for a register. @@ -1085,22 +823,7 @@ update_equiv_regs () = gen_rtx_EXPR_LIST (REG_EQUIV, dest, REG_NOTES (reg_equiv_init_insn[regno])); - /* If this is a register-register copy where SRC is not dead, see if we - can optimize it. */ - if (flag_expensive_optimizations && GET_CODE (dest) == REG - && GET_CODE (SET_SRC (set)) == REG - && ! find_reg_note (insn, REG_DEAD, SET_SRC (set))) - optimize_reg_copy_1 (insn, dest, SET_SRC (set)); - - /* Similarly for a pseudo-pseudo copy when SRC is dead. */ - else if (flag_expensive_optimizations && GET_CODE (dest) == REG - && REGNO (dest) >= FIRST_PSEUDO_REGISTER - && GET_CODE (SET_SRC (set)) == REG - && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER - && find_reg_note (insn, REG_DEAD, SET_SRC (set))) - optimize_reg_copy_2 (insn, dest, SET_SRC (set)); - - /* Otherwise, we only handle the case of a pseudo register being set + /* We only handle the case of a pseudo register being set once and only if neither the source nor the destination are in a register class that's likely to be spilled. */ if (GET_CODE (dest) != REG |