/* Reload pseudo regs into hard regs for insns that require hard regs.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011 Free Software Foundation, Inc.
+ 2011, 2012 Free Software Foundation, Inc.
This file is part of GCC.
be substituted eventually by altering the REG-rtx's. */
grow_reg_equivs ();
- reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
reg_old_renumber = XCNEWVEC (short, max_regno);
memcpy (reg_old_renumber, reg_renumber, max_regno * sizeof (short));
pseudo_forbidden_regs = XNEWVEC (HARD_REG_SET, max_regno);
if (reg_equiv_memory_loc (i))
MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc (i));
else
- {
- MEM_IN_STRUCT_P (reg) = MEM_SCALAR_P (reg) = 0;
- MEM_ATTRS (reg) = 0;
- }
+ MEM_ATTRS (reg) = 0;
MEM_NOTRAP_P (reg) = 1;
}
else if (reg_equiv_mem (i))
case 'p':
cls = (int) reg_class_subunion[cls]
- [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+ [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH)];
break;
case 'g':
default:
if (EXTRA_ADDRESS_CONSTRAINT (c, p))
cls = (int) reg_class_subunion[cls]
- [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+ [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH)];
else
cls = (int) reg_class_subunion[cls]
[(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
}
free (reg_equiv_init_cost);
+ free (offsets_known_at);
+ free (offsets_at);
+ offsets_at = NULL;
+ offsets_known_at = NULL;
}
\f
/* Comparison function for qsort to decide which of two reloads
if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
return 0;
+ /* Reload register of reload with type RELOAD_FOR_INPADDR_ADDRESS
+ could be killed if the register is also used by reload with type
+ RELOAD_FOR_INPUT_ADDRESS, so check it. */
+ if (type == RELOAD_FOR_INPADDR_ADDRESS
+ && TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], regno))
+ return 0;
+
for (i = opnum + 1; i < reload_n_operands; i++)
if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
|| TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
|| TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno))
return 0;
+ /* Reload register of reload with type RELOAD_FOR_OUTADDR_ADDRESS
+ could be killed if the register is also used by reload with type
+ RELOAD_FOR_OUTPUT_ADDRESS, so check it. */
+ if (type == RELOAD_FOR_OUTADDR_ADDRESS
+ && TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
+ return 0;
+
return 1;
default:
}
/* Like reload_reg_reaches_end_p, but check that the condition holds for
- every register in the range [REGNO, REGNO + NREGS). */
+ every register in REG. */
static bool
-reload_regs_reach_end_p (unsigned int regno, int nregs, int reloadnum)
+reload_reg_rtx_reaches_end_p (rtx reg, int reloadnum)
{
- int i;
+ unsigned int i;
- for (i = 0; i < nregs; i++)
- if (!reload_reg_reaches_end_p (regno + i, reloadnum))
+ for (i = REGNO (reg); i < END_REGNO (reg); i++)
+ if (!reload_reg_reaches_end_p (i, reloadnum))
return false;
return true;
}
static rtx other_operand_reload_insns = 0;
static rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
-/* Values to be put in spill_reg_store are put here first. */
+/* Values to be put in spill_reg_store are put here first. Instructions
+ must only be placed here if the associated reload register reaches
+ the end of the instruction's reload sequence. */
static rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
static HARD_REG_SET reg_reloaded_died;
/* Prevent normal processing of this reload. */
special = 1;
- /* Output a special code sequence for this case, and forget about
- spill reg information. */
- new_spill_reg_store[REGNO (reloadreg)] = NULL;
+ /* Output a special code sequence for this case. */
inc_for_reload (reloadreg, oldequiv, rl->out, rl->inc);
}
rld[s].out_reg = rl->out_reg;
set = single_set (next);
if (set && SET_SRC (set) == s_reg
- && ! new_spill_reg_store[REGNO (s_reg)])
+ && reload_reg_rtx_reaches_end_p (s_reg, s))
{
SET_HARD_REG_BIT (reg_is_output_reload,
REGNO (s_reg));
new_spill_reg_store[REGNO (s_reg)] = next;
}
}
- else
+ else if (reload_reg_rtx_reaches_end_p (rl_reg_rtx, j))
new_spill_reg_store[REGNO (rl_reg_rtx)] = p;
}
}
debug_reload_to_stream (dump_file);
}
+ for (j = 0; j < n_reloads; j++)
+ if (rld[j].reg_rtx && HARD_REGISTER_P (rld[j].reg_rtx))
+ {
+ unsigned int i;
+
+ for (i = REGNO (rld[j].reg_rtx); i < END_REGNO (rld[j].reg_rtx); i++)
+ new_spill_reg_store[i] = 0;
+ }
+
/* Now output the instructions to copy the data into and out of the
reload registers. Do these in the order that the reloads were reported,
since reloads of base and index registers precede reloads of operands
for (j = 0; j < n_reloads; j++)
{
- if (rld[j].reg_rtx && HARD_REGISTER_P (rld[j].reg_rtx))
- {
- unsigned int i;
-
- for (i = REGNO (rld[j].reg_rtx); i < END_REGNO (rld[j].reg_rtx); i++)
- new_spill_reg_store[i] = 0;
- }
-
do_input_reload (chain, rld + j, j);
do_output_reload (chain, rld + j, j);
}
&& GET_CODE (rld[r].out) != PRE_MODIFY))))
{
rtx reg;
- enum machine_mode mode;
- int regno, nregs;
reg = reload_reg_rtx_for_output[r];
- mode = GET_MODE (reg);
- regno = REGNO (reg);
- nregs = hard_regno_nregs[regno][mode];
- if (reload_regs_reach_end_p (regno, nregs, r))
+ if (reload_reg_rtx_reaches_end_p (reg, r))
{
+ enum machine_mode mode = GET_MODE (reg);
+ int regno = REGNO (reg);
+ int nregs = hard_regno_nregs[regno][mode];
rtx out = (REG_P (rld[r].out)
? rld[r].out
: rld[r].out_reg
&& !reg_set_p (reload_reg_rtx_for_input[r], PATTERN (insn)))
{
rtx reg;
- enum machine_mode mode;
- int regno, nregs;
reg = reload_reg_rtx_for_input[r];
- mode = GET_MODE (reg);
- regno = REGNO (reg);
- nregs = hard_regno_nregs[regno][mode];
- if (reload_regs_reach_end_p (regno, nregs, r))
+ if (reload_reg_rtx_reaches_end_p (reg, r))
{
+ enum machine_mode mode;
+ int regno;
+ int nregs;
int in_regno;
int in_nregs;
rtx in;
bool piecemeal;
+ mode = GET_MODE (reg);
+ regno = REGNO (reg);
+ nregs = hard_regno_nregs[regno][mode];
if (REG_P (rld[r].in)
&& REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER)
in = rld[r].in;
delete_output_reload. */
src_reg = reload_reg_rtx_for_output[r];
- /* If this is an optional reload, try to find the source reg
- from an input reload. */
- if (! src_reg)
+ if (src_reg)
{
+ if (reload_reg_rtx_reaches_end_p (src_reg, r))
+ store_insn = new_spill_reg_store[REGNO (src_reg)];
+ else
+ src_reg = NULL_RTX;
+ }
+ else
+ {
+ /* If this is an optional reload, try to find the
+ source reg from an input reload. */
rtx set = single_set (insn);
if (set && SET_DEST (set) == rld[r].out)
{
}
}
}
- else
- store_insn = new_spill_reg_store[REGNO (src_reg)];
if (src_reg && REG_P (src_reg)
&& REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
{
if (insn)
{
/* Add a REG_EQUIV note so that find_equiv_reg can find it. */
- set_unique_reg_note (insn, REG_EQUIV, in);
+ set_dst_reg_note (insn, REG_EQUIV, in, out);
return insn;
}
gcc_assert (!reg_overlap_mentioned_p (out, op0));
gen_reload (out, op1, opnum, type);
insn = emit_insn (gen_add2_insn (out, op0));
- set_unique_reg_note (insn, REG_EQUIV, in);
+ set_dst_reg_note (insn, REG_EQUIV, in, out);
}
#ifdef SECONDARY_MEMORY_NEEDED