===================================================================
@@ -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))