diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2005-12-14 23:34:51 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2005-12-14 23:34:51 +0000 |
commit | 7efd40b52ae7678cf00eabee5628ca73aa4ce0cc (patch) | |
tree | 67cd5624f0d306170c0f647905c54c4ce4ad687c /gcc/reload1.c | |
parent | 6f93378c697dbe4a2829de095f354ff2d0acd71e (diff) | |
download | gcc-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.c | 35 |
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 < ®_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 |