/* This obstack is used for allocation of rtl during register elimination.
The allocated storage can be freed once find_reloads has processed the
insn. */
-struct obstack reload_obstack;
+static struct obstack reload_obstack;
/* Points to the beginning of the reload_obstack. All insn_chain structures
are allocated first. */
-char *reload_startobj;
+static char *reload_startobj;
/* The point after all insn_chain structures. Used to quickly deallocate
memory allocated in copy_reloads during calculate_needs_all_insns. */
-char *reload_firstobj;
+static char *reload_firstobj;
/* This points before all local rtl generated by register elimination.
Used to quickly free all memory after processing one insn. */
/* Set during calculate_needs if an insn needs register elimination. */
static int something_needs_elimination;
/* Set during calculate_needs if an insn needs an operand changed. */
-int something_needs_operands_changed;
+static int something_needs_operands_changed;
/* Nonzero means we couldn't get enough spill regs. */
static int failure;
that is not a legitimate memory operand. As later
stages of reload assume that all addresses found
in the reg_equiv_* arrays were originally legitimate,
- we ignore such REG_EQUIV notes. */
- if (memory_operand (x, VOIDmode))
+
+ It can also happen that a REG_EQUIV note contains a
+ readonly memory location. If the destination pseudo
+ is set from some other value (typically a different
+ pseudo), and the destination pseudo does not get a
+ hard reg, then reload will replace the destination
+ pseudo with its equivalent memory location. This
+ is horribly bad as it creates a store to a readonly
+ memory location and a runtime segfault. To avoid
+ this problem we reject readonly memory locations
+ for equivalences. This is overly conservative as
+ we could find all sets of the destination pseudo
+ and remove them as they should be redundant. */
+ if (memory_operand (x, VOIDmode) && ! MEM_READONLY_P (x))
{
/* Always unshare the equivalence, so we can
substitute into this insn without touching the
CLEAR_REGNO_REG_SET (bb->global_live_at_start,
HARD_FRAME_POINTER_REGNUM);
- /* Come here (with failure set nonzero) if we can't get enough spill regs
- and we decide not to abort about it. */
+ /* Come here (with failure set nonzero) if we can't get enough spill
+ regs. */
failed:
CLEAR_REG_SET (&spilled_pseudos);
replace_pseudos_in (& XEXP (PATTERN (insn), 0),
VOIDmode, PATTERN (insn));
+ /* Discard obvious no-ops, even without -O. This optimization
+ is fast and doesn't interfere with debugging. */
+ if (NONJUMP_INSN_P (insn)
+ && GET_CODE (PATTERN (insn)) == SET
+ && REG_P (SET_SRC (PATTERN (insn)))
+ && REG_P (SET_DEST (PATTERN (insn)))
+ && (REGNO (SET_SRC (PATTERN (insn)))
+ == REGNO (SET_DEST (PATTERN (insn)))))
+ {
+ delete_insn (insn);
+ continue;
+ }
+
pnote = ®_NOTES (insn);
while (*pnote != 0)
{
if (size > STACK_CHECK_MAX_FRAME_SIZE)
{
- warning ("frame size too large for reliable stack checking");
+ warning (0, "frame size too large for reliable stack checking");
if (! verbose_warned)
{
- warning ("try reducing the number of local variables");
+ warning (0, "try reducing the number of local variables");
verbose_warned = 1;
}
}
static void
spill_failure (rtx insn, enum reg_class class)
{
- static const char *const reg_class_names[] = REG_CLASS_NAMES;
if (asm_noperands (PATTERN (insn)) >= 0)
error_for_asm (insn, "can't find a register in class %qs while "
"reloading %<asm%>",
unsigned int nr;
/* note_stores does give us subregs of hard regs,
- subreg_regno_offset will abort if it is not a hard reg. */
+ subreg_regno_offset requires a hard reg. */
while (GET_CODE (x) == SUBREG)
{
/* We ignore the subreg offset when calculating the regno,
\f
/* Indexed by reload number, 1 if incoming value
inherited from previous insns. */
-char reload_inherited[MAX_RELOADS];
+static char reload_inherited[MAX_RELOADS];
/* For an inherited reload, this is the insn the reload was inherited from,
if we know it. Otherwise, this is 0. */
-rtx reload_inheritance_insn[MAX_RELOADS];
+static rtx reload_inheritance_insn[MAX_RELOADS];
/* If nonzero, this is a place to get the value of the reload,
rather than using reload_in. */
-rtx reload_override_in[MAX_RELOADS];
+static rtx reload_override_in[MAX_RELOADS];
/* For each reload, the hard register number of the register used,
or -1 if we did not need a register for this reload. */
-int reload_spill_index[MAX_RELOADS];
+static int reload_spill_index[MAX_RELOADS];
/* Subroutine of free_for_value_p, used to check a single register.
START_REGNO is the starting regno of the full reload register
}
/* Return nonzero if the rtx X is invariant over the current function. */
-/* ??? Actually, the places where we use this expect exactly what
- * is tested here, and not everything that is function invariant. In
- * particular, the frame pointer and arg pointer are special cased;
- * pic_offset_table_rtx is not, and this will cause aborts when we
- * go to spill these things to memory. */
+/* ??? Actually, the places where we use this expect exactly what is
+ tested here, and not everything that is function invariant. In
+ particular, the frame pointer and arg pointer are special cased;
+ pic_offset_table_rtx is not, and we must not spill these things to
+ memory. */
static int
function_invariant_p (rtx x)
need_mode = mode;
else
need_mode
- = smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
+ = smallest_mode_for_size (GET_MODE_BITSIZE (mode)
+ + byte * BITS_PER_UNIT,
GET_MODE_CLASS (mode));
- if (
-#ifdef CANNOT_CHANGE_MODE_CLASS
- (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
- need_mode)
- &&
-#endif
- (GET_MODE_SIZE (GET_MODE (last_reg))
+ if ((GET_MODE_SIZE (GET_MODE (last_reg))
>= GET_MODE_SIZE (need_mode))
#ifdef CANNOT_CHANGE_MODE_CLASS
- )
+ /* Verify that the register in "i" can be obtained
+ from LAST_REG. */
+ && !REG_CANNOT_CHANGE_MODE_P (REGNO (last_reg),
+ GET_MODE (last_reg),
+ mode)
#endif
&& reg_reloaded_contents[i] == regno
&& TEST_HARD_REG_BIT (reg_reloaded_valid, i)
gcc_assert (GET_CODE (equiv) == SUBREG);
regno = subreg_regno (equiv);
equiv = gen_rtx_REG (rld[r].mode, regno);
+ /* If we choose EQUIV as the reload register, but the
+ loop below decides to cancel the inheritance, we'll
+ end up reloading EQUIV in rld[r].mode, not the mode
+ it had originally. That isn't safe when EQUIV isn't
+ available as a spill register since its value might
+ still be live at this point. */
+ for (i = regno; i < regno + (int) rld[r].nregs; i++)
+ if (TEST_HARD_REG_BIT (reload_reg_unavailable, i))
+ equiv = 0;
}
}
|| rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
- /* Check to see if we accidentally converted two reloads
- that use the same reload register with different inputs
- to the same type. If so, the resulting code won't work,
- so abort. */
+ /* Check to see if we accidentally converted two
+ reloads that use the same reload register with
+ different inputs to the same type. If so, the
+ resulting code won't work. */
if (rld[j].reg_rtx)
for (k = 0; k < j; k++)
gcc_assert (rld[k].in == 0 || rld[k].reg_rtx == 0