From 4120328793ec55d52d0df4d17980376ecba31cbe Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Wed, 21 May 2014 09:29:34 +0000 Subject: [PATCH] Improve reload code generation by ignoring init insns for reloads. * reload1.c (remove_init_insns, will_delete_init_insn_p): New static functions. (reload, calculate_needs_all_insns, reload_as_needed): Use them. From-SVN: r210685 --- gcc/ChangeLog | 4 ++ gcc/reload1.c | 101 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 68 insertions(+), 37 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac9558695f2d..bfa1ec7eb63d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -198,6 +198,10 @@ 2014-05-19 Bernd Schmidt + * reload1.c (remove_init_insns, will_delete_init_insn_p): New static + functions. + (reload, calculate_needs_all_insns, reload_as_needed): Use them. + * simplify-rtx.c (simplify_unary_operation_1): Use CONST_INT_P in shift simplification where it was intended. diff --git a/gcc/reload1.c b/gcc/reload1.c index 3d735eeeec97..9daafa45097f 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -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))