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;
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
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));