Index: gcc/reload1.c =================================================================== --- gcc/reload1.c (revision 206316) +++ gcc/reload1.c (working copy) @@ -686,6 +686,65 @@ static int failure; /* Temporary array of pseudo-register number. */ static int *temp_pseudo_reg_arr; +/* If a pseudo has no hard reg, delete the insns that made the equivalence. + If that insn didn't set the register (i.e., it copied the register to + memory), just delete that insn instead of the equivalencing insn plus + anything now dead. If we call delete_dead_insn on that insn, we may + delete the insn that actually sets the register if the register dies + there and that is incorrect. */ +static void +remove_init_insns () +{ + for (int i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) + { + if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0) + { + rtx list; + for (list = reg_equiv_init (i); list; list = XEXP (list, 1)) + { + rtx equiv_insn = XEXP (list, 0); + + /* If we already deleted the insn or if it may trap, we can't + delete it. The latter case shouldn't happen, but can + if an insn has a variable address, gets a REG_EH_REGION + note added to it, and then gets converted into a load + from a constant address. */ + if (NOTE_P (equiv_insn) + || can_throw_internal (equiv_insn)) + ; + else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn))) + delete_dead_insn (equiv_insn); + else + SET_INSN_DELETED (equiv_insn); + } + } + } +} + +/* Return true if remove_init_insns will delete INSN. */ +static bool +will_delete_init_insn_p (rtx insn) +{ + rtx set = single_set (insn); + if (!set || !REG_P (SET_DEST (set))) + return false; + unsigned regno = REGNO (SET_DEST (set)); + + if (can_throw_internal (insn)) + return false; + + if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0) + return false; + + for (rtx list = reg_equiv_init (regno); list; list = XEXP (list, 1)) + { + rtx equiv_insn = XEXP (list, 0); + if (equiv_insn == insn) + return true; + } + return false; +} + /* Main entry point for the reload pass. FIRST is the first insn of the function being compiled. @@ -993,37 +1052,7 @@ reload (rtx first, int global) if (ep->can_eliminate) mark_elimination (ep->from, ep->to); - /* If a pseudo has no hard reg, delete the insns that made the equivalence. - If that insn didn't set the register (i.e., it copied the register to - memory), just delete that insn instead of the equivalencing insn plus - anything now dead. If we call delete_dead_insn on that insn, we may - delete the insn that actually sets the register if the register dies - there and that is incorrect. */ - - for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) - { - if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0) - { - rtx list; - for (list = reg_equiv_init (i); list; list = XEXP (list, 1)) - { - rtx equiv_insn = XEXP (list, 0); - - /* If we already deleted the insn or if it may trap, we can't - delete it. The latter case shouldn't happen, but can - if an insn has a variable address, gets a REG_EH_REGION - note added to it, and then gets converted into a load - from a constant address. */ - if (NOTE_P (equiv_insn) - || can_throw_internal (equiv_insn)) - ; - else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn))) - delete_dead_insn (equiv_insn); - else - SET_INSN_DELETED (equiv_insn); - } - } - } + remove_init_insns (); /* Use the reload registers where necessary by generating move instructions to move the must-be-register @@ -1484,14 +1513,9 @@ calculate_needs_all_insns (int global) rtx old_notes = REG_NOTES (insn); int did_elimination = 0; int operands_changed = 0; - rtx set = single_set (insn); /* Skip insns that only set an equivalence. */ - if (set && REG_P (SET_DEST (set)) - && reg_renumber[REGNO (SET_DEST (set))] < 0 - && (reg_equiv_constant (REGNO (SET_DEST (set))) - || (reg_equiv_invariant (REGNO (SET_DEST (set))))) - && reg_equiv_init (REGNO (SET_DEST (set)))) + if (will_delete_init_insn_p (insn)) continue; /* If needed, eliminate any eliminable registers. */ @@ -4586,6 +4610,9 @@ reload_as_needed (int live_known) rtx old_prev = PREV_INSN (insn); #endif + if (will_delete_init_insn_p (insn)) + continue; + /* If we pass a label, copy the offsets from the label information into the current offsets of each elimination. */ if (LABEL_P (insn))