parent
2a5f48f20c
commit
0dadecf681
|
@ -5814,6 +5814,10 @@ cse_insn (insn, in_libcall_block)
|
|||
sets[i].src_in_memory = hash_arg_in_memory;
|
||||
sets[i].src_in_struct = hash_arg_in_struct;
|
||||
|
||||
#if 0
|
||||
/* It is no longer clear why we used to do this, but it doesn't
|
||||
appear to still be needed. So let's try without it since this
|
||||
code hurts cse'ing widened ops. */
|
||||
/* If source is a perverse subreg (such as QI treated as an SI),
|
||||
treat it as volatile. It may do the work of an SI in one context
|
||||
where the extra bits are not being used, but cannot replace an SI
|
||||
|
@ -5822,6 +5826,7 @@ cse_insn (insn, in_libcall_block)
|
|||
&& (GET_MODE_SIZE (GET_MODE (src))
|
||||
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
|
||||
sets[i].src_volatile = 1;
|
||||
#endif
|
||||
|
||||
/* Locate all possible equivalent forms for SRC. Try to replace
|
||||
SRC in the insn with each cheaper equivalent.
|
||||
|
|
|
@ -28,7 +28,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
compiled for the target, and hence definitions concerning only the host
|
||||
do not apply. */
|
||||
|
||||
#include "tm.h"
|
||||
#include "tconfig.h"
|
||||
#ifndef L_trampoline
|
||||
#include "gstddef.h"
|
||||
#endif
|
||||
|
@ -1495,7 +1495,7 @@ __do_global_dtors ()
|
|||
#ifdef DO_GLOBAL_DTORS_BODY
|
||||
DO_GLOBAL_DTORS_BODY;
|
||||
#else
|
||||
unsigned nptrs = (unsigned) __DTOR_LIST__[0];
|
||||
unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
|
||||
unsigned i;
|
||||
|
||||
/* Some systems place the number of pointers
|
||||
|
|
128
gcc/reload.c
128
gcc/reload.c
|
@ -207,6 +207,17 @@ static int n_replacements;
|
|||
static rtx memlocs[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
|
||||
static int n_memlocs;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
|
||||
/* Save MEMs needed to copy from one class of registers to another. One MEM
|
||||
is used per mode, but normally only one or two modes are ever used.
|
||||
|
||||
We keep two versions, before and after register elimination. */
|
||||
|
||||
static rtx secondary_memlocs[NUM_MACHINE_MODES];
|
||||
static rtx secondary_memlocs_elim[NUM_MACHINE_MODES];
|
||||
#endif
|
||||
|
||||
/* The instruction we are doing reloads for;
|
||||
so we can test whether a register dies in it. */
|
||||
static rtx this_insn;
|
||||
|
@ -369,6 +380,73 @@ find_secondary_reload (x, reload_class, reload_mode, in_p, picode, pmode,
|
|||
}
|
||||
#endif /* HAVE_SECONDARY_RELOADS */
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
|
||||
/* Return a memory location that will be used to copy X in mode MODE.
|
||||
If we haven't already made a location for this mode in this insn,
|
||||
call find_reloads_address on the location being returned. */
|
||||
|
||||
rtx
|
||||
get_secondary_mem (x, mode)
|
||||
rtx x;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
rtx loc;
|
||||
int mem_valid;
|
||||
|
||||
/* If MODE is narrower than a word, widen it. This is required because
|
||||
most machines that require these memory locations do not support
|
||||
short load and stores from all registers (e.g., FP registers). We could
|
||||
possibly conditionalize this, but we lose nothing by doing the wider
|
||||
mode. */
|
||||
|
||||
if (GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
|
||||
mode = mode_for_size (BITS_PER_WORD, GET_MODE_CLASS (mode), 0);
|
||||
|
||||
/* If we already have made a MEM for this insn, return it. */
|
||||
if (secondary_memlocs_elim[(int) mode] != 0)
|
||||
return secondary_memlocs_elim[(int) mode];
|
||||
|
||||
/* If this is the first time we've tried to get a MEM for this mode,
|
||||
allocate a new one. `something_changed' in reload will get set
|
||||
by noticing that the frame size has changed. */
|
||||
|
||||
if (secondary_memlocs[(int) mode] == 0)
|
||||
secondary_memlocs[(int) mode]
|
||||
= assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
|
||||
|
||||
/* Get a version of the address doing any eliminations needed. If that
|
||||
didn't give us a new MEM, make a new one if it isn't valid. */
|
||||
|
||||
loc = eliminate_regs (secondary_memlocs[(int) mode], 0, NULL_RTX);
|
||||
mem_valid = strict_memory_address_p (mode, XEXP (loc, 0));
|
||||
|
||||
if (! mem_valid && loc == secondary_memlocs[(int) mode])
|
||||
loc = copy_rtx (loc);
|
||||
|
||||
/* The only time the call below will do anything is if the stack
|
||||
offset is too large. In that case IND_LEVELS doesn't matter, so we
|
||||
can just pass a zero. */
|
||||
if (! mem_valid)
|
||||
find_reloads_address (mode, NULL_PTR, XEXP (loc, 0), &XEXP (loc, 0), x, 0);
|
||||
|
||||
secondary_memlocs_elim[(int) mode] = loc;
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
/* Clear any secondary memory locations we've made. */
|
||||
|
||||
void
|
||||
clear_secondary_mem ()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_MACHINE_MODES; i++)
|
||||
secondary_memlocs[i] = 0;
|
||||
}
|
||||
#endif /* SECONDARY_MEMORY_NEEDED */
|
||||
|
||||
/* Record one (sometimes two) reload that needs to be performed.
|
||||
IN is an rtx saying where the data are to be found before this instruction.
|
||||
OUT says where they must be stored after the instruction.
|
||||
|
@ -569,6 +647,21 @@ push_reload (in, out, inloc, outloc, class,
|
|||
&& reg_overlap_mentioned_for_reload_p (in, XEXP (out, 0)))
|
||||
dont_share = 1;
|
||||
|
||||
/* If IN is a SUBREG of a hard register, make a new REG. This
|
||||
simplifies some of the cases below. */
|
||||
|
||||
if (in != 0 && GET_CODE (in) == SUBREG && GET_CODE (SUBREG_REG (in)) == REG
|
||||
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER)
|
||||
in = gen_rtx (REG, GET_MODE (in),
|
||||
REGNO (SUBREG_REG (in)) + SUBREG_WORD (in));
|
||||
|
||||
/* Similarly for OUT. */
|
||||
if (out != 0 && GET_CODE (out) == SUBREG
|
||||
&& GET_CODE (SUBREG_REG (out)) == REG
|
||||
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER)
|
||||
out = gen_rtx (REG, GET_MODE (out),
|
||||
REGNO (SUBREG_REG (out)) + SUBREG_WORD (out));
|
||||
|
||||
/* Narrow down the class of register wanted if that is
|
||||
desirable on this machine for efficiency. */
|
||||
if (in != 0)
|
||||
|
@ -858,6 +951,19 @@ push_reload (in, out, inloc, outloc, class,
|
|||
|
||||
n_reloads++;
|
||||
i = n_reloads;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we need a memory location to copy between the two
|
||||
reload regs, set it up now. */
|
||||
|
||||
if (in != 0 && secondary_icode == CODE_FOR_nothing
|
||||
&& SECONDARY_MEMORY_NEEDED (secondary_class, class, inmode))
|
||||
get_secondary_mem (in, inmode);
|
||||
|
||||
if (out != 0 && secondary_icode == CODE_FOR_nothing
|
||||
&& SECONDARY_MEMORY_NEEDED (class, secondary_class, outmode))
|
||||
get_secondary_mem (out, outmode);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -883,6 +989,21 @@ push_reload (in, out, inloc, outloc, class,
|
|||
reload_secondary_p[i] = 0;
|
||||
|
||||
n_reloads++;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If a memory location is needed for the copy, make one. */
|
||||
if (in != 0 && GET_CODE (in) == REG
|
||||
&& REGNO (in) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
|
||||
class, inmode))
|
||||
get_secondary_mem (in, inmode);
|
||||
|
||||
if (out != 0 && GET_CODE (out) == REG
|
||||
&& REGNO (out) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (REGNO (out)),
|
||||
outmode))
|
||||
get_secondary_mem (out, outmode);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1829,6 +1950,13 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
|||
no_output_reloads = 1;
|
||||
#endif
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* The eliminated forms of any secondary memory locations are per-insn, so
|
||||
clear them out here. */
|
||||
|
||||
bzero (secondary_memlocs_elim, sizeof secondary_memlocs_elim);
|
||||
#endif
|
||||
|
||||
/* Find what kind of insn this is. NOPERANDS gets number of operands.
|
||||
Make OPERANDS point to a vector of operand values.
|
||||
Make OPERAND_LOCS point to a vector of pointers to
|
||||
|
|
|
@ -513,6 +513,11 @@ reload (first, global, dumpfile)
|
|||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
basic_block_needs[i] = 0;
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* Initialize the secondary memory table. */
|
||||
clear_secondary_mem ();
|
||||
#endif
|
||||
|
||||
/* Remember which hard regs appear explicitly
|
||||
before we merge into `regs_ever_live' the ones in which
|
||||
pseudo regs have been allocated. */
|
||||
|
@ -786,6 +791,7 @@ reload (first, global, dumpfile)
|
|||
rtx max_groups_insn[N_REG_CLASSES];
|
||||
rtx max_nongroups_insn[N_REG_CLASSES];
|
||||
rtx x;
|
||||
int starting_frame_size = get_frame_size ();
|
||||
|
||||
something_changed = 0;
|
||||
bzero (max_needs, sizeof max_needs);
|
||||
|
@ -1302,6 +1308,11 @@ reload (first, global, dumpfile)
|
|||
/* Note that there is a continue statement above. */
|
||||
}
|
||||
|
||||
/* If we allocated any new memory locations, make another pass
|
||||
since it might have changed elimination offsets. */
|
||||
if (starting_frame_size != get_frame_size ())
|
||||
something_changed = 1;
|
||||
|
||||
/* If we have caller-saves, set up the save areas and see if caller-save
|
||||
will need a spill register. */
|
||||
|
||||
|
@ -5298,8 +5309,35 @@ emit_reload_insns (insn)
|
|||
|
||||
/* Output the last reload insn. */
|
||||
if (! special)
|
||||
emit_insn_before (gen_move_insn (old, reloadreg),
|
||||
first_output_reload_insn);
|
||||
{
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we need a memory location to do the move, do it that way. */
|
||||
if (GET_CODE (old) == REG && REGNO (old) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (old)),
|
||||
REGNO_REG_CLASS (REGNO (reloadreg)),
|
||||
GET_MODE (reloadreg)))
|
||||
{
|
||||
/* Get the memory to use and rewrite both registers to
|
||||
its mode. */
|
||||
rtx loc = get_secondary_mem (old, GET_MODE (reloadreg));
|
||||
|
||||
if (GET_MODE (loc) != GET_MODE (reloadreg))
|
||||
reloadreg = gen_rtx (REG, GET_MODE (loc),
|
||||
REGNO (reloadreg));
|
||||
|
||||
if (GET_MODE (loc) != GET_MODE (old))
|
||||
old = gen_rtx (REG, GET_MODE (loc), REGNO (old));
|
||||
|
||||
emit_insn_before (gen_move_insn (loc, reloadreg),
|
||||
first_output_reload_insn);
|
||||
emit_insn_before (gen_move_insn (old, loc),
|
||||
first_output_reload_insn);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
emit_insn_before (gen_move_insn (old, reloadreg),
|
||||
first_output_reload_insn);
|
||||
}
|
||||
|
||||
#ifdef PRESERVE_DEATH_INFO_REGNO_P
|
||||
/* If final will look at death notes for this reg,
|
||||
|
@ -5608,6 +5646,27 @@ gen_input_reload (reloadreg, in, before_insn)
|
|||
emit_insn_before (gen_add2_insn (reloadreg, op1), before_insn);
|
||||
}
|
||||
|
||||
#ifdef SECONDARY_MEMORY_NEEDED
|
||||
/* If we need a memory location to do the move, do it that way. */
|
||||
else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
|
||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
|
||||
REGNO_REG_CLASS (REGNO (reloadreg)),
|
||||
GET_MODE (reloadreg)))
|
||||
{
|
||||
/* Get the memory to use and rewrite both registers to its mode. */
|
||||
rtx loc = get_secondary_mem (in, GET_MODE (reloadreg));
|
||||
|
||||
if (GET_MODE (loc) != GET_MODE (reloadreg))
|
||||
reloadreg = gen_rtx (REG, GET_MODE (loc), REGNO (reloadreg));
|
||||
|
||||
if (GET_MODE (loc) != GET_MODE (in))
|
||||
in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
|
||||
|
||||
emit_insn_before (gen_move_insn (reloadreg, loc), before_insn);
|
||||
emit_insn_before (gen_move_insn (loc, in), before_insn);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If IN is a simple operand, use gen_move_insn. */
|
||||
else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
|
||||
emit_insn_before (gen_move_insn (reloadreg, in), before_insn);
|
||||
|
|
Loading…
Reference in New Issue