aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2006-08-17 09:44:12 +0000
committerJan Hubicka <jh@suse.cz>2006-08-17 09:44:12 +0000
commita129307fb394e5b61978efe1741a37dcb9ee3029 (patch)
tree1387baa691799365777e206414d997c3c6d86614 /gcc
parent63cf3d1189119a6708130da35344cf468b77a7d9 (diff)
PR tree-optimization/27865
* reload1.c (forget_marked_reloads): New function. (forget_old_reloads_1): When data are passed, just mark the registers for later removal. (reload_as_needed): Use the new mechanizm. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@116220 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/reload1.c82
2 files changed, 68 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9794ce2d544..6b36ab8a95f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2006-08-17 Jan Hubicka <jh@suse.cz>
+
+ PR tree-optimization/27865
+ * reload1.c (forget_marked_reloads): New function.
+ (forget_old_reloads_1): When data are passed, just mark the registers
+ for later removal.
+ (reload_as_needed): Use the new mechanizm.
+
2006-08-17 Alexandre Oliva <aoliva@redhat.com>
PR target/28146
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 8ce042fe2c4..a86f6f560e3 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -408,6 +408,7 @@ static void count_pseudo (int);
static void order_regs_for_reload (struct insn_chain *);
static void reload_as_needed (int);
static void forget_old_reloads_1 (rtx, rtx, void *);
+static void forget_marked_reloads (regset);
static int reload_reg_class_lower (const void *, const void *);
static void mark_reload_reg_in_use (unsigned int, int, enum reload_type,
enum machine_mode);
@@ -3907,8 +3908,9 @@ reload_as_needed (int live_known)
else if (INSN_P (insn))
{
- rtx oldpat = copy_rtx (PATTERN (insn));
-
+ regset_head regs_to_forget;
+ INIT_REG_SET (&regs_to_forget);
+ note_stores (PATTERN (insn), forget_old_reloads_1, &regs_to_forget);
/* If this is a USE and CLOBBER of a MEM, ensure that any
references to eliminable registers have been removed. */
@@ -3928,6 +3930,7 @@ reload_as_needed (int live_known)
if (NOTE_P (insn))
{
update_eliminable_offsets ();
+ CLEAR_REG_SET (&regs_to_forget);
continue;
}
}
@@ -4014,7 +4017,8 @@ reload_as_needed (int live_known)
for this insn in order to be stored in
(obeying register constraints). That is correct; such reload
registers ARE still valid. */
- note_stores (oldpat, forget_old_reloads_1, NULL);
+ forget_marked_reloads (&regs_to_forget);
+ CLEAR_REG_SET (&regs_to_forget);
/* There may have been CLOBBER insns placed after INSN. So scan
between INSN and NEXT and use them to forget old reloads. */
@@ -4163,14 +4167,18 @@ reload_as_needed (int live_known)
unless X is an output reload reg of the current insn.
X may be a hard reg (the reload reg)
- or it may be a pseudo reg that was reloaded from. */
+ or it may be a pseudo reg that was reloaded from.
+
+ When DATA is non-NULL just mark the registers in regset
+ to be forgotten later. */
static void
forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
+ void *data)
{
unsigned int regno;
unsigned int nr;
+ regset regs = (regset) data;
/* note_stores does give us subregs of hard regs,
subreg_regno_offset requires a hard reg. */
@@ -4198,26 +4206,56 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
This can happen if a block-local pseudo is allocated to that reg
and it wasn't spilled because this block's total need is 0.
Then some insn might have an optional reload and use this reg. */
- for (i = 0; i < nr; i++)
- /* But don't do this if the reg actually serves as an output
- reload reg in the current instruction. */
- if (n_reloads == 0
- || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
- {
- CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
- CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + i);
- spill_reg_store[regno + i] = 0;
- }
+ if (!regs)
+ for (i = 0; i < nr; i++)
+ /* But don't do this if the reg actually serves as an output
+ reload reg in the current instruction. */
+ if (n_reloads == 0
+ || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
+ {
+ CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+ CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + i);
+ spill_reg_store[regno + i] = 0;
+ }
}
- /* Since value of X has changed,
- forget any value previously copied from it. */
+ if (regs)
+ while (nr-- > 0)
+ SET_REGNO_REG_SET (regs, regno + nr);
+ else
+ {
+ /* Since value of X has changed,
+ forget any value previously copied from it. */
+
+ while (nr-- > 0)
+ /* But don't forget a copy if this is the output reload
+ that establishes the copy's validity. */
+ if (n_reloads == 0 || reg_has_output_reload[regno + nr] == 0)
+ reg_last_reload_reg[regno + nr] = 0;
+ }
+}
- while (nr-- > 0)
- /* But don't forget a copy if this is the output reload
- that establishes the copy's validity. */
- if (n_reloads == 0 || reg_has_output_reload[regno + nr] == 0)
- reg_last_reload_reg[regno + nr] = 0;
+/* Forget the reloads marked in regset by previous function. */
+static void
+forget_marked_reloads (regset regs)
+{
+ unsigned int reg;
+ reg_set_iterator rsi;
+ EXECUTE_IF_SET_IN_REG_SET (regs, 0, reg, rsi)
+ {
+ if (reg < FIRST_PSEUDO_REGISTER
+ /* But don't do this if the reg actually serves as an output
+ reload reg in the current instruction. */
+ && (n_reloads == 0
+ || ! TEST_HARD_REG_BIT (reg_is_output_reload, reg)))
+ {
+ CLEAR_HARD_REG_BIT (reg_reloaded_valid, reg);
+ CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, reg);
+ spill_reg_store[reg] = 0;
+ }
+ if (n_reloads == 0 || reg_has_output_reload[reg] == 0)
+ reg_last_reload_reg[reg] = 0;
+ }
}
/* The following HARD_REG_SETs indicate when each hard register is