diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 447dc85588b..d56233977f6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2007-04-27 Richard Sandiford + + * reload.h (elimination_target_reg_p): Declare. + * reload.c (find_reloads): Don't apply the reg_rtx move + optimization if the SET_DEST satisfies elimination_target_reg_p. + * reload1.c (elimination_target_reg_p): New function. + (gen_reload): In the move/add2 fallback, make sure that op0 + does not overlap the destination register. + 2007-04-27 Zdenek Dvorak * tree-ssa-loop-im.c (determine_invariantness_stmt): Attempt to diff --git a/gcc/reload.c b/gcc/reload.c index de6093b0339..8ed2f4b3880 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4465,7 +4465,8 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known, if (rld[i].when_needed == RELOAD_FOR_INPUT && GET_CODE (PATTERN (insn)) == SET && REG_P (SET_DEST (PATTERN (insn))) - && SET_SRC (PATTERN (insn)) == rld[i].in) + && SET_SRC (PATTERN (insn)) == rld[i].in + && !elimination_target_reg_p (SET_DEST (PATTERN (insn)))) { rtx dest = SET_DEST (PATTERN (insn)); unsigned int regno = REGNO (dest); diff --git a/gcc/reload.h b/gcc/reload.h index 6de5e8471bf..38d340fd5cd 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -342,6 +342,7 @@ extern void mark_home_live (int); /* Scan X and replace any eliminable registers (such as fp) with a replacement (such as sp), plus an offset. */ extern rtx eliminate_regs (rtx, enum machine_mode, rtx); +extern bool elimination_target_reg_p (rtx); /* Deallocate the reload register used by reload number R. */ extern void deallocate_reload_reg (int r); diff --git a/gcc/reload1.c b/gcc/reload1.c index 9ee046ae1ec..4d2dea520b8 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -3607,6 +3607,20 @@ update_eliminables (HARD_REG_SET *pset) SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM); } +/* Return true if X is used as the target register of an elimination. */ + +bool +elimination_target_reg_p (rtx x) +{ + struct elim_table *ep; + + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + if (ep->to_rtx == x && ep->can_eliminate) + return true; + + return false; +} + /* Initialize the table of registers to eliminate. */ static void @@ -7873,6 +7887,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type) /* If that failed, copy the address register to the reload register. Then add the constant to the reload register. */ + gcc_assert (!reg_overlap_mentioned_p (out, op0)); gen_reload (out, op1, opnum, type); insn = emit_insn (gen_add2_insn (out, op0)); set_unique_reg_note (insn, REG_EQUIV, in);