summaryrefslogtreecommitdiff
path: root/gcc/sched-deps.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/sched-deps.c')
-rw-r--r--gcc/sched-deps.c177
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;
}