diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-09-11 19:28:11 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-09-11 19:28:11 +0000 |
commit | 8ad6f16d6c5d94a95dbd85fe112f933eea2b561f (patch) | |
tree | 74dbbe65149d2c089f7ca72ba460cd78dd473966 /gcc/sched-deps.c | |
parent | 0237e47b14de480975bbde36671f134234817b8a (diff) | |
download | gcc-8ad6f16d6c5d94a95dbd85fe112f933eea2b561f.tar.gz |
PR rtl-optimization/28726
* sched-deps.c (sched_analyze_reg): New function extracted from...
(sched_analyze_1): ...here. Call it to analyze references to
registers. Treat again writes to a stack register as writing to the
register.
(sched_analyze_2): ...and here. Call it to analyze references to
registers. Treat again reads of a stack register as reading the
register.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116855 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/sched-deps.c')
-rw-r--r-- | gcc/sched-deps.c | 177 |
1 files changed, 87 insertions, 90 deletions
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index a408fab0706..0cde4f2e94f 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -715,6 +715,78 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read, deps->pending_flush_length = 1; } +/* Analyze a single reference to register (reg:MODE REGNO) in INSN. + The type of the reference is specified by REF and can be SET, + CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE. */ + +static void +sched_analyze_reg (struct deps *deps, int regno, enum machine_mode mode, + enum rtx_code ref, rtx insn) +{ + /* A hard reg in a wide mode may really be multiple registers. + If so, mark all of them just like the first. */ + if (regno < FIRST_PSEUDO_REGISTER) + { + int i = hard_regno_nregs[regno][mode]; + if (ref == SET) + { + while (--i >= 0) + SET_REGNO_REG_SET (reg_pending_sets, regno + i); + } + else if (ref == USE) + { + while (--i >= 0) + SET_REGNO_REG_SET (reg_pending_uses, regno + i); + } + else + { + while (--i >= 0) + SET_REGNO_REG_SET (reg_pending_clobbers, regno + i); + } + } + + /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that + it does not reload. Ignore these as they have served their + purpose already. */ + else if (regno >= deps->max_reg) + { + enum rtx_code code = GET_CODE (PATTERN (insn)); + gcc_assert (code == USE || code == CLOBBER); + } + + else + { + if (ref == SET) + SET_REGNO_REG_SET (reg_pending_sets, regno); + else if (ref == USE) + SET_REGNO_REG_SET (reg_pending_uses, regno); + else + SET_REGNO_REG_SET (reg_pending_clobbers, regno); + + /* Pseudos that are REG_EQUIV to something may be replaced + by that during reloading. We need only add dependencies for + the address in the REG_EQUIV note. */ + if (!reload_completed && get_reg_known_equiv_p (regno)) + { + rtx t = get_reg_known_value (regno); + if (MEM_P (t)) + sched_analyze_2 (deps, XEXP (t, 0), insn); + } + + /* Don't let it cross a call after scheduling if it doesn't + already cross one. */ + if (REG_N_CALLS_CROSSED (regno) == 0) + { + if (ref == USE) + deps->sched_before_next_call + = alloc_INSN_LIST (insn, deps->sched_before_next_call); + else + add_dependence_list (insn, deps->last_function_call, 1, + REG_DEP_ANTI); + } + } +} + /* Analyze a single SET, CLOBBER, PRE_DEC, POST_DEC, PRE_INC or POST_INC rtx, X, creating all dependencies generated by the write to the destination of X, and reads of everything mentioned. */ @@ -722,7 +794,6 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read, static void sched_analyze_1 (struct deps *deps, rtx x, rtx insn) { - int regno; rtx dest = XEXP (x, 0); enum rtx_code code = GET_CODE (x); @@ -771,64 +842,21 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn) if (REG_P (dest)) { - regno = REGNO (dest); + int regno = REGNO (dest); + enum machine_mode mode = GET_MODE (dest); + + sched_analyze_reg (deps, regno, mode, code, insn); #ifdef STACK_REGS /* Treat all writes to a stack register as modifying the TOS. */ if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG) { - SET_REGNO_REG_SET (reg_pending_uses, FIRST_STACK_REG); - regno = FIRST_STACK_REG; + /* Avoid analyzing the same register twice. */ + if (regno != FIRST_STACK_REG) + sched_analyze_reg (deps, FIRST_STACK_REG, mode, code, insn); + sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn); } #endif - - /* A hard reg in a wide mode may really be multiple registers. - If so, mark all of them just like the first. */ - if (regno < FIRST_PSEUDO_REGISTER) - { - int i = hard_regno_nregs[regno][GET_MODE (dest)]; - if (code == SET) - { - while (--i >= 0) - SET_REGNO_REG_SET (reg_pending_sets, regno + i); - } - else - { - while (--i >= 0) - SET_REGNO_REG_SET (reg_pending_clobbers, regno + i); - } - } - /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that - it does not reload. Ignore these as they have served their - purpose already. */ - else if (regno >= deps->max_reg) - { - gcc_assert (GET_CODE (PATTERN (insn)) == USE - || GET_CODE (PATTERN (insn)) == CLOBBER); - } - else - { - if (code == SET) - SET_REGNO_REG_SET (reg_pending_sets, regno); - else - SET_REGNO_REG_SET (reg_pending_clobbers, regno); - - /* Pseudos that are REG_EQUIV to something may be replaced - by that during reloading. We need only add dependencies for - the address in the REG_EQUIV note. */ - if (!reload_completed && get_reg_known_equiv_p (regno)) - { - rtx t = get_reg_known_value (regno); - if (MEM_P (t)) - sched_analyze_2 (deps, XEXP (t, 0), insn); - } - - /* Don't let it cross a call after scheduling if it doesn't - already cross one. */ - if (REG_N_CALLS_CROSSED (regno) == 0) - add_dependence_list (insn, deps->last_function_call, 1, - REG_DEP_ANTI); - } } else if (MEM_P (dest)) { @@ -935,51 +963,20 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn) case REG: { int regno = REGNO (x); + enum machine_mode mode = GET_MODE (x); + + sched_analyze_reg (deps, regno, mode, USE, insn); #ifdef STACK_REGS /* Treat all reads of a stack register as modifying the TOS. */ if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG) { - SET_REGNO_REG_SET (reg_pending_sets, FIRST_STACK_REG); - regno = FIRST_STACK_REG; + /* Avoid analyzing the same register twice. */ + if (regno != FIRST_STACK_REG) + sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn); + sched_analyze_reg (deps, FIRST_STACK_REG, mode, SET, insn); } #endif - - if (regno < FIRST_PSEUDO_REGISTER) - { - int i = hard_regno_nregs[regno][GET_MODE (x)]; - while (--i >= 0) - SET_REGNO_REG_SET (reg_pending_uses, regno + i); - } - /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that - it does not reload. Ignore these as they have served their - purpose already. */ - else if (regno >= deps->max_reg) - { - gcc_assert (GET_CODE (PATTERN (insn)) == USE - || GET_CODE (PATTERN (insn)) == CLOBBER); - } - else - { - SET_REGNO_REG_SET (reg_pending_uses, regno); - - /* Pseudos that are REG_EQUIV to something may be replaced - by that during reloading. We need only add dependencies for - the address in the REG_EQUIV note. */ - if (!reload_completed && get_reg_known_equiv_p (regno)) - { - rtx t = get_reg_known_value (regno); - if (MEM_P (t)) - sched_analyze_2 (deps, XEXP (t, 0), insn); - } - - /* If the register does not already cross any calls, then add this - insn to the sched_before_next_call list so that it will still - not cross calls after scheduling. */ - if (REG_N_CALLS_CROSSED (regno) == 0) - deps->sched_before_next_call - = alloc_INSN_LIST (insn, deps->sched_before_next_call); - } return; } |