Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* This file contains subroutines used only from the file reload1.c.
It knows how to scan one insn for operands and values
#include "rtl.h"
#include "tm_p.h"
#include "insn-config.h"
+#include "expr.h"
+#include "optabs.h"
#include "recog.h"
#include "reload.h"
#include "regs.h"
#include "real.h"
#include "output.h"
#include "function.h"
-#include "expr.h"
#include "toplev.h"
#ifndef REGISTER_MOVE_COST
#endif
static enum reg_class find_valid_class PARAMS ((enum machine_mode, int));
static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode));
-static int push_reload PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
- enum machine_mode, enum machine_mode,
- int, int, int, enum reload_type));
static void push_replacement PARAMS ((rtx *, int, enum machine_mode));
static void combine_reloads PARAMS ((void));
static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class,
the two reload-numbers are equal, but the caller should be careful to
distinguish them. */
-static int
+int
push_reload (in, out, inloc, outloc, class,
inmode, outmode, strict_low, optional, opnum, type)
rtx in, out;
rld[i].opnum = MIN (rld[i].opnum, opnum);
}
- /* If the ostensible rtx being reload differs from the rtx found
+ /* If the ostensible rtx being reloaded differs from the rtx found
in the location to substitute, this reload is not safe to combine
because we cannot reliably tell whether it appears in the insn. */
register char *p = constraints[i];
register int win = 0;
int did_match = 0;
- /* 0 => this operand can be reloaded somehow for this alternative */
+ /* 0 => this operand can be reloaded somehow for this alternative. */
int badop = 1;
/* 0 => this operand can be reloaded if the alternative allows regs. */
int winreg = 0;
|| (REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0)))
win = 1;
- /* Drop through into 'r' case */
+ /* Drop through into 'r' case. */
case 'r':
this_alternative[i]
if (GET_CODE (insn) != JUMP_INSN
&& GET_CODE (substitution) == LABEL_REF
&& !find_reg_note (insn, REG_LABEL, XEXP (substitution, 0)))
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL,
+ REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
XEXP (substitution, 0),
REG_NOTES (insn));
}
x = find_reloads_subreg_address (x, 1, opnum, type, ind_levels,
insn);
}
- else if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM
- && (GET_MODE_SIZE (GET_MODE (x))
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
- && mode_dependent_address_p (XEXP (SUBREG_REG (x), 0)))
- {
- /* A paradoxical subreg will simply have the mode of the access
- changed, so we need to reload such a memory operand to stabilize
- the meaning of the memory access. */
- enum machine_mode subreg_mode = GET_MODE (SUBREG_REG (x));
-
- /* SUBREG_REG (x) is a MEM, so we cant take the offset, instead we
- calculate the register number as :
- SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode) */
- if (is_set_dest)
- push_reload (NULL_RTX, SUBREG_REG (x), (rtx*)0, &SUBREG_REG (x),
- find_valid_class (subreg_mode,
- SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
- VOIDmode, subreg_mode, 0, 0, opnum, type);
- else
- push_reload (SUBREG_REG (x), NULL_RTX, &SUBREG_REG (x), (rtx*)0,
- find_valid_class (subreg_mode,
- SUBREG_BYTE (x) / GET_MODE_SIZE (subreg_mode)),
- subreg_mode, VOIDmode, 0, 0, opnum, type);
- }
for (copied = 0, i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
tem = copy_rtx (tem);
tem = replace_equiv_address_nv (reg_equiv_memory_loc[regno], tem);
- return adjust_address_nv (tem, GET_MODE (ad), 0);
+ tem = adjust_address_nv (tem, GET_MODE (ad), 0);
+
+ /* Copy the result if it's still the same as the equivalence, to avoid
+ modifying it when we do the substitution for the reload. */
+ if (tem == reg_equiv_memory_loc[regno])
+ tem = copy_rtx (tem);
+ return tem;
}
/* Record all reloads needed for handling memory address AD
regno = REGNO (ad);
/* If the register is equivalent to an invariant expression, substitute
- the invariant, and eliminate any eliminable register references. */
+ the invariant, and eliminate any eliminable register references. */
tem = reg_equiv_constant[regno];
if (tem != 0
&& (tem = eliminate_regs (tem, mode, insn))
into a register. */
if (CONSTANT_P (ad) && ! strict_memory_address_p (mode, ad))
{
- /* If AD is in address in the constant pool, the MEM rtx may be shared.
+ /* If AD is an address in the constant pool, the MEM rtx may be shared.
Unshare it so we can safely alter it. */
if (memrefloc && GET_CODE (ad) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (ad))
/* Note that we take shortcuts assuming that no multi-reg machine mode
occurs as part of an address.
Also, this is not fully machine-customizable; it works for machines
- such as vaxes and 68000's and 32000's, but other possible machines
+ such as VAXen and 68000's and 32000's, but other possible machines
could have addressing modes that this does not handle right. */
static int
register rtx reloadreg = rld[r->what].reg_rtx;
if (reloadreg)
{
+#ifdef ENABLE_CHECKING
+ /* Internal consistency test. Check that we don't modify
+ anything in the equivalence arrays. Whenever something from
+ those arrays needs to be reloaded, it must be unshared before
+ being substituted into; the equivalence must not be modified.
+ Otherwise, if the equivalence is used after that, it will
+ have been modified, and the thing substituted (probably a
+ register) is likely overwritten and not a usable equivalence. */
+ int check_regno;
+
+ for (check_regno = 0; check_regno < max_regno; check_regno++)
+ {
+#define CHECK_MODF(ARRAY) \
+ if (ARRAY[check_regno] \
+ && loc_mentioned_in_p (r->where, \
+ ARRAY[check_regno])) \
+ abort ()
+
+ CHECK_MODF (reg_equiv_constant);
+ CHECK_MODF (reg_equiv_memory_loc);
+ CHECK_MODF (reg_equiv_address);
+ CHECK_MODF (reg_equiv_mem);
+#undef CHECK_MODF
+ }
+#endif /* ENABLE_CHECKING */
+
/* If we're replacing a LABEL_REF with a register, add a
REG_LABEL note to indicate to flow which label this
register refers to. */
if (GET_CODE (*r->where) == LABEL_REF
&& GET_CODE (insn) == JUMP_INSN)
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL,
+ REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL,
XEXP (*r->where, 0),
REG_NOTES (insn));
contains a MEM (we don't bother checking for memory addresses that can't
conflict because we expect this to be a rare case.
- This function is similar to reg_overlap_mention_p in rtlanal.c except
+ This function is similar to reg_overlap_mentioned_p in rtlanal.c except
that we look at equivalences for pseudos that didn't get hard registers. */
int
for (i = 0; i < valuenregs; ++i)
if (call_used_regs[valueno + i])
return 0;
- }
-
#ifdef NON_SAVING_SETJMP
- if (NON_SAVING_SETJMP && GET_CODE (p) == NOTE
- && NOTE_LINE_NUMBER (p) == NOTE_INSN_SETJMP)
- return 0;
+ if (NON_SAVING_SETJMP && find_reg_note (p, REG_SETJMP, NULL))
+ return 0;
#endif
+ }
if (INSN_P (p))
{