aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/lra.c')
-rw-r--r--gcc/lra.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/gcc/lra.c b/gcc/lra.c
index 5d1f429658f..bdd8e3ca3df 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -1777,9 +1777,10 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
/* Replace all references to register OLD_REGNO in *LOC with pseudo
- register NEW_REG. Return true if any change was made. */
+ register NEW_REG. Try to simplify subreg of constant if SUBREG_P.
+ Return true if any change was made. */
bool
-lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
+lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p)
{
rtx x = *loc;
bool result = false;
@@ -1791,9 +1792,25 @@ lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
return false;
code = GET_CODE (x);
- if (code == REG && (int) REGNO (x) == old_regno)
+ if (code == SUBREG && subreg_p)
{
- machine_mode mode = GET_MODE (*loc);
+ rtx subst, inner = SUBREG_REG (x);
+ /* Transform subreg of constant while we still have inner mode
+ of the subreg. The subreg internal should not be an insn
+ operand. */
+ if (REG_P (inner) && (int) REGNO (inner) == old_regno
+ && CONSTANT_P (new_reg)
+ && (subst = simplify_subreg (GET_MODE (x), new_reg, GET_MODE (inner),
+ SUBREG_BYTE (x))) != NULL_RTX)
+ {
+ *loc = subst;
+ return true;
+ }
+
+ }
+ else if (code == REG && (int) REGNO (x) == old_regno)
+ {
+ machine_mode mode = GET_MODE (x);
machine_mode inner_mode = GET_MODE (new_reg);
if (mode != inner_mode
@@ -1815,26 +1832,30 @@ lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
{
if (fmt[i] == 'e')
{
- if (lra_substitute_pseudo (&XEXP (x, i), old_regno, new_reg))
+ if (lra_substitute_pseudo (&XEXP (x, i), old_regno,
+ new_reg, subreg_p))
result = true;
}
else if (fmt[i] == 'E')
{
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno, new_reg))
+ if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno,
+ new_reg, subreg_p))
result = true;
}
}
return result;
}
-/* Call lra_substitute_pseudo within an insn. This won't update the insn ptr,
- just the contents of the insn. */
+/* Call lra_substitute_pseudo within an insn. Try to simplify subreg
+ of constant if SUBREG_P. This won't update the insn ptr, just the
+ contents of the insn. */
bool
-lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, rtx new_reg)
+lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno,
+ rtx new_reg, bool subreg_p)
{
rtx loc = insn;
- return lra_substitute_pseudo (&loc, old_regno, new_reg);
+ return lra_substitute_pseudo (&loc, old_regno, new_reg, subreg_p);
}