aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@gcc.gnu.org>2011-06-01 19:47:19 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2011-06-01 19:47:19 +0000
commit4d41c2d1ce6f01c53eb8941461b3047e8a6368f6 (patch)
tree9a0f3ba878d421d60706ace98a062816b5c78465 /gcc/reload1.c
parent7448d2e73ea9513f001327757541328bb8137b38 (diff)
downloadgcc-4d41c2d1ce6f01c53eb8941461b3047e8a6368f6.zip
gcc-4d41c2d1ce6f01c53eb8941461b3047e8a6368f6.tar.gz
gcc-4d41c2d1ce6f01c53eb8941461b3047e8a6368f6.tar.bz2
re PR rtl-optimization/48830 (unrecognized insn: storing invalid upper FP reg in SImode)
gcc/ PR rtl-optimization/48830 PR rtl-optimization/48808 PR rtl-optimization/48792 * reload.c (push_reload): Check contains_reg_of_mode. * reload1.c (strip_paradoxical_subreg): New function. (gen_reload_chain_without_interm_reg_p): Use it to handle paradoxical subregs. (emit_output_reload_insns, gen_reload): Likewise. gcc/testsuite/ 2011-06-01 Eric Botcazou <ebotcazou@adacore.com> Hans-Peter Nilsson <hp@axis.com> PR rtl-optimization/48830 * gcc.target/sparc/ultrasp12.c: New test. From-SVN: r174540
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r--gcc/reload1.c66
1 files changed, 42 insertions, 24 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index ea7df99..e65503b 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -4471,6 +4471,43 @@ scan_paradoxical_subregs (rtx x)
}
}
}
+
+/* *OP_PTR and *OTHER_PTR are two operands to a conceptual reload.
+ If *OP_PTR is a paradoxical subreg, try to remove that subreg
+ and apply the corresponding narrowing subreg to *OTHER_PTR.
+ Return true if the operands were changed, false otherwise. */
+
+static bool
+strip_paradoxical_subreg (rtx *op_ptr, rtx *other_ptr)
+{
+ rtx op, inner, other, tem;
+
+ op = *op_ptr;
+ if (GET_CODE (op) != SUBREG)
+ return false;
+
+ inner = SUBREG_REG (op);
+ if (GET_MODE_SIZE (GET_MODE (op)) <= GET_MODE_SIZE (GET_MODE (inner)))
+ return false;
+
+ other = *other_ptr;
+ tem = gen_lowpart_common (GET_MODE (inner), other);
+ if (!tem)
+ return false;
+
+ /* If the lowpart operation turned a hard register into a subreg,
+ rather than simplifying it to another hard register, then the
+ mode change cannot be properly represented. For example, OTHER
+ might be valid in its current mode, but not in the new one. */
+ if (GET_CODE (tem) == SUBREG
+ && REG_P (other)
+ && HARD_REGISTER_P (other))
+ return false;
+
+ *op_ptr = inner;
+ *other_ptr = tem;
+ return true;
+}
/* A subroutine of reload_as_needed. If INSN has a REG_EH_REGION note,
examine all of the reload insns between PREV and NEXT exclusive, and
@@ -5538,7 +5575,7 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
chain reloads or do need an intermediate hard registers. */
bool result = true;
int regno, n, code;
- rtx out, in, tem, insn;
+ rtx out, in, insn;
rtx last = get_last_insn ();
/* Make r2 a component of r1. */
@@ -5557,11 +5594,7 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
/* If IN is a paradoxical SUBREG, remove it and try to put the
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
- if (GET_CODE (in) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (in))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
- && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (in)), out)) != 0)
- in = SUBREG_REG (in), out = tem;
+ strip_paradoxical_subreg (&in, &out);
if (GET_CODE (in) == PLUS
&& (REG_P (XEXP (in, 0))
@@ -7557,7 +7590,6 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
if (tertiary_icode != CODE_FOR_nothing)
{
rtx third_reloadreg = rld[tertiary_reload].reg_rtx;
- rtx tem;
/* Copy primary reload reg to secondary reload reg.
(Note that these have been swapped above, then
@@ -7566,13 +7598,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
/* If REAL_OLD is a paradoxical SUBREG, remove it
and try to put the opposite SUBREG on
RELOADREG. */
- if (GET_CODE (real_old) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (real_old))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (real_old))))
- && 0 != (tem = gen_lowpart_common
- (GET_MODE (SUBREG_REG (real_old)),
- reloadreg)))
- real_old = SUBREG_REG (real_old), reloadreg = tem;
+ strip_paradoxical_subreg (&real_old, &reloadreg);
gen_reload (reloadreg, second_reloadreg,
rl->opnum, rl->when_needed);
@@ -8388,16 +8414,8 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
/* If IN is a paradoxical SUBREG, remove it and try to put the
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
- if (GET_CODE (in) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (in))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
- && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (in)), out)) != 0)
- in = SUBREG_REG (in), out = tem;
- else if (GET_CODE (out) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (out))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
- && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (out)), in)) != 0)
- out = SUBREG_REG (out), in = tem;
+ if (!strip_paradoxical_subreg (&in, &out))
+ strip_paradoxical_subreg (&out, &in);
/* How to do this reload can get quite tricky. Normally, we are being
asked to reload a simple operand, such as a MEM, a constant, or a pseudo