aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload1.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2005-12-14 23:34:51 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2005-12-14 23:34:51 +0000
commit7efd40b52ae7678cf00eabee5628ca73aa4ce0cc (patch)
tree67cd5624f0d306170c0f647905c54c4ce4ad687c /gcc/reload1.c
parent6f93378c697dbe4a2829de095f354ff2d0acd71e (diff)
downloadgcc-7efd40b52ae7678cf00eabee5628ca73aa4ce0cc.zip
gcc-7efd40b52ae7678cf00eabee5628ca73aa4ce0cc.tar.gz
gcc-7efd40b52ae7678cf00eabee5628ca73aa4ce0cc.tar.bz2
re PR rtl-optimization/25310 (ICE in reload_cse_simplify_operands, at postreload.c:393)
PR rtl-optimization/25310 * reload1.c (eliminate_regs_in_insn): Handle lowpart SUBREGs of the eliminable register when substituting into a PLUS. PR rtl-optimization/25310 * gcc.c-torture/compile/pr25310.c: New test. From-SVN: r108543
Diffstat (limited to 'gcc/reload1.c')
-rw-r--r--gcc/reload1.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 970f5ec..29da121 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -3006,42 +3006,57 @@ eliminate_regs_in_insn (rtx insn, int replace)
{
if (GET_CODE (SET_SRC (old_set)) == PLUS)
plus_src = SET_SRC (old_set);
- /* First see if the source is of the form (plus (reg) CST). */
+ /* First see if the source is of the form (plus (...) CST). */
if (plus_src
- && REG_P (XEXP (plus_src, 0))
- && GET_CODE (XEXP (plus_src, 1)) == CONST_INT
- && REGNO (XEXP (plus_src, 0)) < FIRST_PSEUDO_REGISTER)
+ && GET_CODE (XEXP (plus_src, 1)) == CONST_INT)
plus_cst_src = plus_src;
else if (REG_P (SET_SRC (old_set))
|| plus_src)
{
/* Otherwise, see if we have a REG_EQUAL note of the form
- (plus (reg) CST). */
+ (plus (...) CST). */
rtx links;
for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
{
if (REG_NOTE_KIND (links) == REG_EQUAL
&& GET_CODE (XEXP (links, 0)) == PLUS
- && REG_P (XEXP (XEXP (links, 0), 0))
- && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT
- && REGNO (XEXP (XEXP (links, 0), 0)) < FIRST_PSEUDO_REGISTER)
+ && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT)
{
plus_cst_src = XEXP (links, 0);
break;
}
}
}
+
+ /* Check that the first operand of the PLUS is a hard reg or
+ the lowpart subreg of one. */
+ if (plus_cst_src)
+ {
+ rtx reg = XEXP (plus_cst_src, 0);
+ if (GET_CODE (reg) == SUBREG && subreg_lowpart_p (reg))
+ reg = SUBREG_REG (reg);
+
+ if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+ plus_cst_src = 0;
+ }
}
if (plus_cst_src)
{
rtx reg = XEXP (plus_cst_src, 0);
HOST_WIDE_INT offset = INTVAL (XEXP (plus_cst_src, 1));
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
if (ep->from_rtx == reg && ep->can_eliminate)
{
+ rtx to_rtx = ep->to_rtx;
offset += ep->offset;
+ if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
+ to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),
+ to_rtx);
if (offset == 0)
{
int num_clobbers;
@@ -3051,7 +3066,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
There's not much we can do if that doesn't work. */
PATTERN (insn) = gen_rtx_SET (VOIDmode,
SET_DEST (old_set),
- ep->to_rtx);
+ to_rtx);
num_clobbers = 0;
INSN_CODE (insn) = recog (PATTERN (insn), insn, &num_clobbers);
if (num_clobbers)
@@ -3081,7 +3096,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
PATTERN (insn) = new_body;
old_set = single_set (insn);
- XEXP (SET_SRC (old_set), 0) = ep->to_rtx;
+ XEXP (SET_SRC (old_set), 0) = to_rtx;
XEXP (SET_SRC (old_set), 1) = GEN_INT (offset);
}
else