Commit d9983d6c by Richard Kenner

(optimize_reg_copy_1): Tighten up code to properly handle the case when...

(optimize_reg_copy_1): Tighten up code to properly handle the case
when SRC or DEST is a multi-word hard register and only some parts of
the register are set or used.  Also, avoid updating register status
for DEST if we can't do the optimization.

From-SVN: r2380
parent dd2cc343
...@@ -686,11 +686,16 @@ optimize_reg_copy_1 (insn, dest, src) ...@@ -686,11 +686,16 @@ optimize_reg_copy_1 (insn, dest, src)
&& reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0)))) && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
break; break;
if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0) /* 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 failed = 0;
int length = 0; int length = 0;
int d_length = 0;
int n_calls = 0; int n_calls = 0;
int d_n_calls = 0;
/* We can do the optimization. Scan forward from INSN again, /* We can do the optimization. Scan forward from INSN again,
replacing regs as we go. Set FAILED if a replacement can't replacing regs as we go. Set FAILED if a replacement can't
...@@ -702,9 +707,23 @@ optimize_reg_copy_1 (insn, dest, src) ...@@ -702,9 +707,23 @@ optimize_reg_copy_1 (insn, dest, src)
q != next_real_insn (p); q != next_real_insn (p);
q = next_real_insn (q)) q = next_real_insn (q))
{ {
if (reg_mentioned_p (src, PATTERN (q))) if (reg_overlap_mentioned_p (src, PATTERN (q)))
{ {
if (validate_replace_rtx (src, dest, 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 /* We assume that a register is used exactly once per
insn in the updates below. If this is not correct, insn in the updates below. If this is not correct,
...@@ -715,26 +734,31 @@ optimize_reg_copy_1 (insn, dest, src) ...@@ -715,26 +734,31 @@ optimize_reg_copy_1 (insn, dest, src)
reg_n_refs[dregno] += loop_depth; reg_n_refs[dregno] += loop_depth;
} }
else else
failed = 1; {
validate_replace_rtx (dest, src, q);
failed = 1;
}
} }
/* Count the insns and CALL_INSNs passed. If we passed the /* Count the insns and CALL_INSNs passed. If we passed the
death note of DEST, show increased live length. */ death note of DEST, show increased live length. */
length++; length++;
if (dest_death) if (dest_death)
reg_live_length[dregno]++; d_length++;
if (GET_CODE (q) == CALL_INSN) if (GET_CODE (q) == CALL_INSN)
{ {
n_calls++; n_calls++;
if (dest_death) if (dest_death)
reg_n_calls_crossed[dregno]++; d_n_calls++;
} }
/* If DEST dies here, remove the death note and save it for /* If DEST dies here, remove the death note and save it for
later. */ later. Make sure ALL of DEST dies here; again, this is
overly conservative. */
if (dest_death == 0 if (dest_death == 0
&& (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0) && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0
&& GET_MODE (XEXP (dest_death, 0)) == GET_MODE (dest))
remove_note (q, dest_death); remove_note (q, dest_death);
} }
...@@ -746,6 +770,12 @@ optimize_reg_copy_1 (insn, dest, src) ...@@ -746,6 +770,12 @@ optimize_reg_copy_1 (insn, dest, src)
reg_n_calls_crossed[sregno] -= n_calls; reg_n_calls_crossed[sregno] -= n_calls;
} }
if (dregno >= FIRST_PSEUDO_REGISTER)
{
reg_live_length[dregno] += d_length;
reg_n_calls_crossed[dregno] += d_n_calls;
}
/* Move death note of SRC from P to INSN. */ /* Move death note of SRC from P to INSN. */
remove_note (p, note); remove_note (p, note);
XEXP (note, 1) = REG_NOTES (insn); XEXP (note, 1) = REG_NOTES (insn);
...@@ -761,6 +791,12 @@ optimize_reg_copy_1 (insn, dest, src) ...@@ -761,6 +791,12 @@ optimize_reg_copy_1 (insn, dest, src)
return; return;
} }
/* 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;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment