aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2014-05-21 09:29:34 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2014-05-21 09:29:34 +0000
commit4120328793ec55d52d0df4d17980376ecba31cbe (patch)
tree77fb31b7521622814daf1b72a017853d5b55a7cd
parent0836b77f3d4aa937d0a60dd292301a1021fa5272 (diff)
downloadgcc-4120328793ec55d52d0df4d17980376ecba31cbe.zip
gcc-4120328793ec55d52d0df4d17980376ecba31cbe.tar.gz
gcc-4120328793ec55d52d0df4d17980376ecba31cbe.tar.bz2
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
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/reload1.c101
2 files changed, 68 insertions, 37 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac95586..bfa1ec7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -198,6 +198,10 @@
2014-05-19 Bernd Schmidt <bernds@codesourcery.com>
+ * 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 3d735ee..9daafa4 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))