/* Search an insn for pseudo regs that must be in hard regs and are not.
- Copyright (C) 1987-2013 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "rtl-error.h"
#include "tm_p.h"
#include "insn-config.h"
+#include "symtab.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "rtl.h"
+#include "flags.h"
+#include "alias.h"
+#include "tree.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
#include "expr.h"
+#include "insn-codes.h"
#include "optabs.h"
#include "recog.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "predict.h"
+#include "basic-block.h"
#include "df.h"
#include "reload.h"
#include "regs.h"
#include "addresses.h"
-#include "hard-reg-set.h"
-#include "flags.h"
-#include "function.h"
#include "params.h"
#include "target.h"
#include "ira.h"
{
rtx *where; /* Location to store in */
int what; /* which reload this is for */
- enum machine_mode mode; /* mode it must have */
+ machine_mode mode; /* mode it must have */
};
static struct replacement replacements[MAX_RECOG_OPERANDS * ((MAX_REGS_PER_ADDRESS * 2) + 1)];
/* The instruction we are doing reloads for;
so we can test whether a register dies in it. */
-static rtx this_insn;
+static rtx_insn *this_insn;
/* Nonzero if this instruction is a user-specified asm with operands. */
static int this_insn_is_asm;
: (type)))
static int push_secondary_reload (int, rtx, int, int, enum reg_class,
- enum machine_mode, enum reload_type,
+ machine_mode, enum reload_type,
enum insn_code *, secondary_reload_info *);
-static enum reg_class find_valid_class (enum machine_mode, enum machine_mode,
+static enum reg_class find_valid_class (machine_mode, machine_mode,
int, unsigned int);
-static void push_replacement (rtx *, int, enum machine_mode);
+static void push_replacement (rtx *, int, machine_mode);
static void dup_replacements (rtx *, rtx *);
static void combine_reloads (void);
static int find_reusable_reload (rtx *, rtx, enum reg_class,
enum reload_type, int, int);
-static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, enum machine_mode,
- enum machine_mode, reg_class_t, int, int);
+static rtx find_dummy_reload (rtx, rtx, rtx *, rtx *, machine_mode,
+ machine_mode, reg_class_t, int, int);
static int hard_reg_set_here_p (unsigned int, unsigned int, rtx);
static struct decomposition decompose (rtx);
static int immune_p (rtx, rtx, struct decomposition);
static bool alternative_allows_const_pool_ref (rtx, const char *, int);
-static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int, rtx,
- int *);
+static rtx find_reloads_toplev (rtx, int, enum reload_type, int, int,
+ rtx_insn *, int *);
static rtx make_memloc (rtx, int);
-static int maybe_memory_address_addr_space_p (enum machine_mode, rtx,
+static int maybe_memory_address_addr_space_p (machine_mode, rtx,
addr_space_t, rtx *);
-static int find_reloads_address (enum machine_mode, rtx *, rtx, rtx *,
- int, enum reload_type, int, rtx);
-static rtx subst_reg_equivs (rtx, rtx);
+static int find_reloads_address (machine_mode, rtx *, rtx, rtx *,
+ int, enum reload_type, int, rtx_insn *);
+static rtx subst_reg_equivs (rtx, rtx_insn *);
static rtx subst_indexed_address (rtx);
-static void update_auto_inc_notes (rtx, int, int);
-static int find_reloads_address_1 (enum machine_mode, addr_space_t, rtx, int,
+static void update_auto_inc_notes (rtx_insn *, int, int);
+static int find_reloads_address_1 (machine_mode, addr_space_t, rtx, int,
enum rtx_code, enum rtx_code, rtx *,
- int, enum reload_type,int, rtx);
+ int, enum reload_type,int, rtx_insn *);
static void find_reloads_address_part (rtx, rtx *, enum reg_class,
- enum machine_mode, int,
+ machine_mode, int,
enum reload_type, int);
static rtx find_reloads_subreg_address (rtx, int, enum reload_type,
- int, rtx, int *);
+ int, rtx_insn *, int *);
static void copy_replacements_1 (rtx *, rtx *, int);
static int find_inc_amount (rtx, rtx);
static int refers_to_mem_for_reload_p (rtx);
static int
push_secondary_reload (int in_p, rtx x, int opnum, int optional,
enum reg_class reload_class,
- enum machine_mode reload_mode, enum reload_type type,
+ machine_mode reload_mode, enum reload_type type,
enum insn_code *picode, secondary_reload_info *prev_sri)
{
enum reg_class rclass = NO_REGS;
enum reg_class scratch_class;
- enum machine_mode mode = reload_mode;
+ machine_mode mode = reload_mode;
enum insn_code icode = CODE_FOR_nothing;
enum insn_code t_icode = CODE_FOR_nothing;
enum reload_type secondary_type;
int s_reload, t_reload = -1;
const char *scratch_constraint;
- char letter;
secondary_reload_info sri;
if (type == RELOAD_FOR_INPUT_ADDRESS
scratch_constraint++;
if (*scratch_constraint == '&')
scratch_constraint++;
- letter = *scratch_constraint;
- scratch_class = (letter == 'r' ? GENERAL_REGS
- : REG_CLASS_FROM_CONSTRAINT ((unsigned char) letter,
- scratch_constraint));
+ scratch_class = (reg_class_for_constraint
+ (lookup_constraint (scratch_constraint)));
rclass = scratch_class;
mode = insn_data[(int) icode].operand[2].mode;
register and a scratch register is needed, we return the class of the
intermediate register. */
reg_class_t
-secondary_reload_class (bool in_p, reg_class_t rclass, enum machine_mode mode,
+secondary_reload_class (bool in_p, reg_class_t rclass, machine_mode mode,
rtx x)
{
enum insn_code icode;
scratch_reload_class (enum insn_code icode)
{
const char *scratch_constraint;
- char scratch_letter;
enum reg_class rclass;
gcc_assert (insn_data[(int) icode].n_operands == 3);
scratch_constraint++;
if (*scratch_constraint == '&')
scratch_constraint++;
- scratch_letter = *scratch_constraint;
- if (scratch_letter == 'r')
- return GENERAL_REGS;
- rclass = REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter,
- scratch_constraint);
+ rclass = reg_class_for_constraint (lookup_constraint (scratch_constraint));
gcc_assert (rclass != NO_REGS);
return rclass;
}
call find_reloads_address on the location being returned. */
rtx
-get_secondary_mem (rtx x ATTRIBUTE_UNUSED, enum machine_mode mode,
+get_secondary_mem (rtx x ATTRIBUTE_UNUSED, machine_mode mode,
int opnum, enum reload_type type)
{
rtx loc;
into REGNO. Such a class must exist. */
static enum reg_class
-find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
- enum machine_mode inner ATTRIBUTE_UNUSED, int n,
+find_valid_class (machine_mode outer ATTRIBUTE_UNUSED,
+ machine_mode inner ATTRIBUTE_UNUSED, int n,
unsigned int dest_regno ATTRIBUTE_UNUSED)
{
int best_cost = -1;
which we would eventually like to obtain the object. */
static enum reg_class
-find_valid_class_1 (enum machine_mode outer ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
+find_valid_class_1 (machine_mode outer ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
enum reg_class dest_class ATTRIBUTE_UNUSED)
{
int best_cost = -1;
the function is invoked for the output part of an enclosing reload. */
static bool
-reload_inner_reg_of_subreg (rtx x, enum machine_mode mode, bool output)
+reload_inner_reg_of_subreg (rtx x, machine_mode mode, bool output)
{
rtx inner;
patterns by register elimination and substituting pseudos without a home
by their function-invariant equivalences. */
static int
-can_reload_into (rtx in, int regno, enum machine_mode mode)
+can_reload_into (rtx in, int regno, machine_mode mode)
{
- rtx dst, test_insn;
+ rtx dst;
+ rtx_insn *test_insn;
int r = 0;
struct recog_data_d save_recog_data;
/* If we can make a simple SET insn that does the job, everything should
be fine. */
dst = gen_rtx_REG (mode, regno);
- test_insn = make_insn_raw (gen_rtx_SET (VOIDmode, dst, in));
+ test_insn = make_insn_raw (gen_rtx_SET (dst, in));
save_recog_data = recog_data;
if (recog_memoized (test_insn) >= 0)
{
extract_insn (test_insn);
- r = constrain_operands (1);
+ r = constrain_operands (1, get_enabled_alternatives (test_insn));
}
recog_data = save_recog_data;
return r;
int
push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
- enum reg_class rclass, enum machine_mode inmode,
- enum machine_mode outmode, int strict_low, int optional,
+ enum reg_class rclass, machine_mode inmode,
+ machine_mode outmode, int strict_low, int optional,
int opnum, enum reload_type type)
{
int i;
is specified. */
if (this_insn_is_asm)
{
- enum machine_mode mode;
+ machine_mode mode;
if (GET_MODE_SIZE (inmode) > GET_MODE_SIZE (outmode))
mode = inmode;
else
{
rtx note;
int regno;
- enum machine_mode rel_mode = inmode;
+ machine_mode rel_mode = inmode;
if (out && GET_MODE_SIZE (outmode) > GET_MODE_SIZE (inmode))
rel_mode = outmode;
&& reg_mentioned_p (XEXP (note, 0), in)
/* Check that a former pseudo is valid; see find_dummy_reload. */
&& (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
- || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+ || (! bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
ORIGINAL_REGNO (XEXP (note, 0)))
&& hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1))
&& ! refers_to_regno_for_reload_p (regno,
end_hard_regno (rel_mode,
regno),
PATTERN (this_insn), inloc)
+ && ! find_reg_fusage (this_insn, USE, XEXP (note, 0))
/* If this is also an output reload, IN cannot be used as
the reload register if it is set in this insn unless IN
is also OUT. */
This is used in insn patterns that use match_dup. */
static void
-push_replacement (rtx *loc, int reloadnum, enum machine_mode mode)
+push_replacement (rtx *loc, int reloadnum, machine_mode mode)
{
if (replace_reloads)
{
&& !fixed_regs[regno]
/* Check that a former pseudo is valid; see find_dummy_reload. */
&& (ORIGINAL_REGNO (XEXP (note, 0)) < FIRST_PSEUDO_REGISTER
- || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+ || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
ORIGINAL_REGNO (XEXP (note, 0)))
&& hard_regno_nregs[regno][GET_MODE (XEXP (note, 0))] == 1)))
{
static rtx
find_dummy_reload (rtx real_in, rtx real_out, rtx *inloc, rtx *outloc,
- enum machine_mode inmode, enum machine_mode outmode,
+ machine_mode inmode, machine_mode outmode,
reg_class_t rclass, int for_real, int earlyclobber)
{
rtx in = real_in;
can ignore the conflict). We must never introduce writes
to such hardregs, as they would clobber the other live
pseudo. See PR 20973. */
- || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR),
+ || (!bitmap_bit_p (DF_LR_OUT (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
ORIGINAL_REGNO (in))
/* Similarly, only do this if we can be sure that the death
note is still valid. global can assign some hardreg to
proper kind of hard reg. */
int
-strict_memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+strict_memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED,
rtx addr, addr_space_t as)
{
#ifdef GO_IF_LEGITIMATE_ADDRESS
return 0;
case LABEL_REF:
- return XEXP (x, 0) == XEXP (y, 0);
+ return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
case SYMBOL_REF:
return XSTR (x, 0) == XSTR (y, 0);
commutative operands, reg_equiv_address substitution, or whatever. */
int
-find_reloads (rtx insn, int replace, int ind_levels, int live_known,
+find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
short *reload_reg_p)
{
int insn_code_number;
rtx body = PATTERN (insn);
rtx set = single_set (insn);
int goal_earlyclobber = 0, this_earlyclobber;
- enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+ machine_mode operand_mode[MAX_RECOG_OPERANDS];
int retval = 0;
this_insn = insn;
if (JUMP_P (insn) || CALL_P (insn))
no_output_reloads = 1;
-#ifdef HAVE_cc0
- if (reg_referenced_p (cc0_rtx, PATTERN (insn)))
+ if (HAVE_cc0 && reg_referenced_p (cc0_rtx, PATTERN (insn)))
no_input_reloads = 1;
- if (reg_set_p (cc0_rtx, PATTERN (insn)))
+ if (HAVE_cc0 && reg_set_p (cc0_rtx, PATTERN (insn)))
no_output_reloads = 1;
-#endif
#ifdef SECONDARY_MEMORY_NEEDED
/* The eliminated forms of any secondary memory locations are per-insn, so
this_insn_is_asm = insn_code_number < 0;
memcpy (operand_mode, recog_data.operand_mode,
- noperands * sizeof (enum machine_mode));
+ noperands * sizeof (machine_mode));
memcpy (constraints, recog_data.constraints,
noperands * sizeof (const char *));
if (*constraints[i] == 0)
/* Ignore things like match_operator operands. */
;
- else if (constraints[i][0] == 'p'
- || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
+ else if (insn_extra_address_constraint
+ (lookup_constraint (constraints[i])))
{
address_operand_reloaded[i]
= find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
First loop over alternatives. */
+ alternative_mask enabled = get_enabled_alternatives (insn);
for (this_alternative_number = 0;
this_alternative_number < n_alternatives;
this_alternative_number++)
{
int swapped;
- if (!recog_data.alternative_enabled_p[this_alternative_number])
+ if (!TEST_BIT (enabled, this_alternative_number))
{
int i;
if (swapped)
{
- enum reg_class tclass;
- int t;
-
recog_data.operand[commutative] = substed_operand[commutative + 1];
recog_data.operand[commutative + 1] = substed_operand[commutative];
/* Swap the duplicates too. */
*recog_data.dup_loc[i]
= recog_data.operand[(int) recog_data.dup_num[i]];
- tclass = preferred_class[commutative];
- preferred_class[commutative] = preferred_class[commutative + 1];
- preferred_class[commutative + 1] = tclass;
-
- t = pref_or_nothing[commutative];
- pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
- pref_or_nothing[commutative + 1] = t;
-
- t = address_reloaded[commutative];
- address_reloaded[commutative] = address_reloaded[commutative + 1];
- address_reloaded[commutative + 1] = t;
+ std::swap (preferred_class[commutative],
+ preferred_class[commutative + 1]);
+ std::swap (pref_or_nothing[commutative],
+ pref_or_nothing[commutative + 1]);
+ std::swap (address_reloaded[commutative],
+ address_reloaded[commutative + 1]);
}
this_earlyclobber = 0;
operand. */
int constmemok = 0;
int earlyclobber = 0;
+ enum constraint_num cn;
+ enum reg_class cl;
/* If the predicate accepts a unary operator, it means that
we need to reload the operand, but do not do this for
c = '\0';
break;
- case '=': case '+': case '*':
- break;
-
- case '%':
- /* We only support one commutative marker, the first
- one. We already set commutative above. */
- break;
-
case '?':
reject += 6;
break;
earlyclobber = 1, this_earlyclobber = 1;
break;
- case 'E':
- case 'F':
- if (CONST_DOUBLE_AS_FLOAT_P (operand)
- || (GET_CODE (operand) == CONST_VECTOR
- && (GET_MODE_CLASS (GET_MODE (operand))
- == MODE_VECTOR_FLOAT)))
- win = 1;
- break;
-
- case 'G':
- case 'H':
- if (CONST_DOUBLE_AS_FLOAT_P (operand)
- && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
- win = 1;
- break;
-
- case 's':
- if (CONST_SCALAR_INT_P (operand))
- break;
- case 'i':
- if (CONSTANT_P (operand)
- && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
- win = 1;
- break;
-
- case 'n':
- if (CONST_SCALAR_INT_P (operand))
- win = 1;
- break;
-
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- if (CONST_INT_P (operand)
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
- win = 1;
- break;
-
case 'X':
force_reload = 0;
win = 1;
|| (REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0)))
win = 1;
- /* Drop through into 'r' case. */
-
- case 'r':
- this_alternative[i]
- = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+ cl = GENERAL_REGS;
goto reg;
default:
- if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
+ cn = lookup_constraint (p);
+ switch (get_constraint_type (cn))
{
-#ifdef EXTRA_CONSTRAINT_STR
- if (EXTRA_MEMORY_CONSTRAINT (c, p))
- {
- if (force_reload)
- break;
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
- win = 1;
- /* If the address was already reloaded,
- we win as well. */
- else if (MEM_P (operand)
- && address_reloaded[i] == 1)
- win = 1;
- /* Likewise if the address will be reloaded because
- reg_equiv_address is nonzero. For reg_equiv_mem
- we have to check. */
- else if (REG_P (operand)
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_renumber[REGNO (operand)] < 0
- && ((reg_equiv_mem (REGNO (operand)) != 0
- && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
- || (reg_equiv_address (REGNO (operand)) != 0)))
- win = 1;
-
- /* If we didn't already win, we can reload
- constants via force_const_mem, and other
- MEMs by reloading the address like for 'o'. */
- if (CONST_POOL_OK_P (operand_mode[i], operand)
- || MEM_P (operand))
- badop = 0;
- constmemok = 1;
- offmemok = 1;
- break;
- }
- if (EXTRA_ADDRESS_CONSTRAINT (c, p))
- {
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
- win = 1;
-
- /* If we didn't already win, we can reload
- the address into a base register. */
- this_alternative[i]
- = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
- ADDRESS, SCRATCH);
- badop = 0;
- break;
- }
+ case CT_REGISTER:
+ cl = reg_class_for_constraint (cn);
+ if (cl != NO_REGS)
+ goto reg;
+ break;
+
+ case CT_CONST_INT:
+ if (CONST_INT_P (operand)
+ && (insn_const_int_ok_for_constraint
+ (INTVAL (operand), cn)))
+ win = true;
+ break;
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
+ case CT_MEMORY:
+ if (force_reload)
+ break;
+ if (constraint_satisfied_p (operand, cn))
+ win = 1;
+ /* If the address was already reloaded,
+ we win as well. */
+ else if (MEM_P (operand) && address_reloaded[i] == 1)
+ win = 1;
+ /* Likewise if the address will be reloaded because
+ reg_equiv_address is nonzero. For reg_equiv_mem
+ we have to check. */
+ else if (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0
+ && ((reg_equiv_mem (REGNO (operand)) != 0
+ && (constraint_satisfied_p
+ (reg_equiv_mem (REGNO (operand)),
+ cn)))
+ || (reg_equiv_address (REGNO (operand))
+ != 0)))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ constants via force_const_mem, and other
+ MEMs by reloading the address like for 'o'. */
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
+ || MEM_P (operand))
+ badop = 0;
+ constmemok = 1;
+ offmemok = 1;
+ break;
+
+ case CT_ADDRESS:
+ if (constraint_satisfied_p (operand, cn))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ the address into a base register. */
+ this_alternative[i]
+ = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH);
+ badop = 0;
+ break;
+
+ case CT_FIXED_FORM:
+ if (constraint_satisfied_p (operand, cn))
win = 1;
-#endif
break;
}
+ break;
- this_alternative[i]
- = (reg_class_subunion
- [this_alternative[i]]
- [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
reg:
+ this_alternative[i]
+ = reg_class_subunion[this_alternative[i]][cl];
if (GET_MODE (operand) == BLKmode)
break;
winreg = 1;
if (swapped)
{
- enum reg_class tclass;
- int t;
-
/* If the commutative operands have been swapped, swap
them back in order to check the next alternative. */
recog_data.operand[commutative] = substed_operand[commutative];
= recog_data.operand[(int) recog_data.dup_num[i]];
/* Unswap the operand related information as well. */
- tclass = preferred_class[commutative];
- preferred_class[commutative] = preferred_class[commutative + 1];
- preferred_class[commutative + 1] = tclass;
-
- t = pref_or_nothing[commutative];
- pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
- pref_or_nothing[commutative + 1] = t;
-
- t = address_reloaded[commutative];
- address_reloaded[commutative] = address_reloaded[commutative + 1];
- address_reloaded[commutative + 1] = t;
+ std::swap (preferred_class[commutative],
+ preferred_class[commutative + 1]);
+ std::swap (pref_or_nothing[commutative],
+ pref_or_nothing[commutative + 1]);
+ std::swap (address_reloaded[commutative],
+ address_reloaded[commutative + 1]);
}
}
}
if (goal_alternative_swapped)
{
- rtx tem;
-
- tem = substed_operand[commutative];
- substed_operand[commutative] = substed_operand[commutative + 1];
- substed_operand[commutative + 1] = tem;
- tem = recog_data.operand[commutative];
- recog_data.operand[commutative] = recog_data.operand[commutative + 1];
- recog_data.operand[commutative + 1] = tem;
- tem = *recog_data.operand_loc[commutative];
- *recog_data.operand_loc[commutative]
- = *recog_data.operand_loc[commutative + 1];
- *recog_data.operand_loc[commutative + 1] = tem;
+ std::swap (substed_operand[commutative],
+ substed_operand[commutative + 1]);
+ std::swap (recog_data.operand[commutative],
+ recog_data.operand[commutative + 1]);
+ std::swap (*recog_data.operand_loc[commutative],
+ *recog_data.operand_loc[commutative + 1]);
+
+ for (i = 0; i < recog_data.n_dups; i++)
+ if (recog_data.dup_num[i] == commutative
+ || recog_data.dup_num[i] == commutative + 1)
+ *recog_data.dup_loc[i]
+ = recog_data.operand[(int) recog_data.dup_num[i]];
for (i = 0; i < n_reloads; i++)
{
rtx op = recog_data.operand[i];
rtx subreg = NULL_RTX;
rtx plus = NULL_RTX;
- enum machine_mode mode = operand_mode[i];
+ machine_mode mode = operand_mode[i];
/* Reloads of SUBREGs of CONSTANT RTXs are handled later in
push_reload so we have to let them pass here. */
use the default address mode as mode of the reload register,
as would have been done by find_reloads_address. */
addr_space_t as = MEM_ADDR_SPACE (recog_data.operand[i]);
- enum machine_mode address_mode;
+ machine_mode address_mode;
address_mode = get_address_mode (recog_data.operand[i]);
operand_reloadnum[i]
this instruction. */
if (GET_CODE (substitution) == LABEL_REF
&& !find_reg_note (insn, REG_LABEL_OPERAND,
- XEXP (substitution, 0))
+ LABEL_REF_LABEL (substitution))
/* For a JUMP_P, if it was a branch target it must have
already been recorded as such. */
&& (!JUMP_P (insn)
- || !label_is_jump_target_p (XEXP (substitution, 0),
+ || !label_is_jump_target_p (LABEL_REF_LABEL (substitution),
insn)))
{
- add_reg_note (insn, REG_LABEL_OPERAND, XEXP (substitution, 0));
- if (LABEL_P (XEXP (substitution, 0)))
- ++LABEL_NUSES (XEXP (substitution, 0));
+ add_reg_note (insn, REG_LABEL_OPERAND,
+ LABEL_REF_LABEL (substitution));
+ if (LABEL_P (LABEL_REF_LABEL (substitution)))
+ ++LABEL_NUSES (LABEL_REF_LABEL (substitution));
}
}
rld[j].in = 0;
}
-#ifdef HAVE_cc0
/* If we made any reloads for addresses, see if they violate a
"no input reloads" requirement for this insn. But loads that we
do after the insn (such as for output addresses) are fine. */
- if (no_input_reloads)
+ if (HAVE_cc0 && no_input_reloads)
for (i = 0; i < n_reloads; i++)
gcc_assert (rld[i].in == 0
|| rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS
|| rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS);
-#endif
/* Compute reload_mode and reload_nregs. */
for (i = 0; i < n_reloads; i++)
for (; (c = *constraint) && c != ',' && c != '#';
constraint += CONSTRAINT_LEN (c, constraint))
{
- if (c == TARGET_MEM_CONSTRAINT || c == 'o')
- return true;
-#ifdef EXTRA_CONSTRAINT_STR
- if (EXTRA_MEMORY_CONSTRAINT (c, constraint)
- && (mem == NULL || EXTRA_CONSTRAINT_STR (mem, c, constraint)))
+ enum constraint_num cn = lookup_constraint (constraint);
+ if (insn_extra_memory_constraint (cn)
+ && (mem == NULL || constraint_satisfied_p (mem, cn)))
return true;
-#endif
}
return false;
}
static rtx
find_reloads_toplev (rtx x, int opnum, enum reload_type type,
- int ind_levels, int is_set_dest, rtx insn,
+ int ind_levels, int is_set_dest, rtx_insn *insn,
int *address_reloaded)
{
RTX_CODE code = GET_CODE (x);
by PART into a register. */
static int
-maybe_memory_address_addr_space_p (enum machine_mode mode, rtx ad,
+maybe_memory_address_addr_space_p (machine_mode mode, rtx ad,
addr_space_t as, rtx *part)
{
int retv;
to a hard register, and frame pointer elimination. */
static int
-find_reloads_address (enum machine_mode mode, rtx *memrefloc, rtx ad,
+find_reloads_address (machine_mode mode, rtx *memrefloc, rtx ad,
rtx *loc, int opnum, enum reload_type type,
- int ind_levels, rtx insn)
+ int ind_levels, rtx_insn *insn)
{
addr_space_t as = memrefloc? MEM_ADDR_SPACE (*memrefloc)
: ADDR_SPACE_GENERIC;
#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
|| operand == hard_frame_pointer_rtx
#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- || operand == arg_pointer_rtx
-#endif
+ || (FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+ && operand == arg_pointer_rtx)
|| operand == stack_pointer_rtx)
&& ! maybe_memory_address_addr_space_p
(mode, ad, as, &XEXP (XEXP (ad, 0), 1 - op_index)))
into a register. */
if (CONSTANT_P (ad) && ! strict_memory_address_addr_space_p (mode, ad, as))
{
- enum machine_mode address_mode = GET_MODE (ad);
+ machine_mode address_mode = GET_MODE (ad);
if (address_mode == VOIDmode)
address_mode = targetm.addr_space.address_mode (as);
front of it for pseudos that we have to replace with stack slots. */
static rtx
-subst_reg_equivs (rtx ad, rtx insn)
+subst_reg_equivs (rtx ad, rtx_insn *insn)
{
RTX_CODE code = GET_CODE (ad);
int i;
This routine assumes both inputs are already in canonical form. */
rtx
-form_sum (enum machine_mode mode, rtx x, rtx y)
+form_sum (machine_mode mode, rtx x, rtx y)
{
rtx tem;
RELOADNUM is the reload number. */
static void
-update_auto_inc_notes (rtx insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
+update_auto_inc_notes (rtx_insn *insn ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED,
int reloadnum ATTRIBUTE_UNUSED)
{
#ifdef AUTO_INC_DEC
handles those cases gracefully. */
static int
-find_reloads_address_1 (enum machine_mode mode, addr_space_t as,
+find_reloads_address_1 (machine_mode mode, addr_space_t as,
rtx x, int context,
enum rtx_code outer_code, enum rtx_code index_code,
rtx *loc, int opnum, enum reload_type type,
- int ind_levels, rtx insn)
+ int ind_levels, rtx_insn *insn)
{
#define REG_OK_FOR_CONTEXT(CONTEXT, REGNO, MODE, AS, OUTER, INDEX) \
((CONTEXT) == 0 \
enum reg_class context_reg_class;
RTX_CODE code = GET_CODE (x);
+ bool reloaded_inner_of_autoinc = false;
if (context == 1)
context_reg_class = INDEX_REG_CLASS;
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum, type,
ind_levels, insn);
+ reloaded_inner_of_autoinc = true;
if (!rtx_equal_p (tem, orig))
push_reg_equiv_alt_mem (regno, tem);
/* Put this inside a new increment-expression. */
enum insn_code icode = optab_handler (add_optab, GET_MODE (x));
if (insn && NONJUMP_INSN_P (insn) && equiv
&& memory_operand (equiv, GET_MODE (equiv))
-#ifdef HAVE_cc0
+#if HAVE_cc0
&& ! sets_cc0_p (PATTERN (insn))
#endif
&& ! (icode != CODE_FOR_nothing
&& insn_operand_matches (icode, 0, equiv)
- && insn_operand_matches (icode, 1, equiv)))
+ && insn_operand_matches (icode, 1, equiv))
+ /* Using RELOAD_OTHER means we emit this and the reload we
+ made earlier in the wrong order. */
+ && !reloaded_inner_of_autoinc)
{
/* We use the original pseudo for loc, so that
emit_reload_insns() knows which pseudo this
static void
find_reloads_address_part (rtx x, rtx *loc, enum reg_class rclass,
- enum machine_mode mode, int opnum,
+ machine_mode mode, int opnum,
enum reload_type type, int ind_levels)
{
if (CONSTANT_P (x)
static rtx
find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
- int ind_levels, rtx insn, int *address_reloaded)
+ int ind_levels, rtx_insn *insn,
+ int *address_reloaded)
{
- enum machine_mode outer_mode = GET_MODE (x);
- enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+ machine_mode outer_mode = GET_MODE (x);
+ machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
int regno = REGNO (SUBREG_REG (x));
int reloaded = 0;
rtx tem, orig;
Return the rtx that X translates into; usually X, but modified. */
void
-subst_reloads (rtx insn)
+subst_reloads (rtx_insn *insn)
{
int i;
return 0;
}
- endregno = END_HARD_REGNO (x);
+ endregno = END_REGNO (x);
return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
}
as if it were a constant except that sp is required to be unchanging. */
rtx
-find_equiv_reg (rtx goal, rtx insn, enum reg_class rclass, int other,
- short *reload_reg_p, int goalreg, enum machine_mode mode)
+find_equiv_reg (rtx goal, rtx_insn *insn, enum reg_class rclass, int other,
+ short *reload_reg_p, int goalreg, machine_mode mode)
{
- rtx p = insn;
- rtx goaltry, valtry, value, where;
+ rtx_insn *p = insn;
+ rtx goaltry, valtry, value;
+ rtx_insn *where;
rtx pat;
int regno = -1;
int valueno;
REG_INC. REGNO must refer to a hard register. */
int
-regno_clobbered_p (unsigned int regno, rtx insn, enum machine_mode mode,
+regno_clobbered_p (unsigned int regno, rtx_insn *insn, machine_mode mode,
int sets)
{
unsigned int nregs, endregno;
/* Find the low part, with mode MODE, of a hard regno RELOADREG. */
rtx
-reload_adjust_reg_for_mode (rtx reloadreg, enum machine_mode mode)
+reload_adjust_reg_for_mode (rtx reloadreg, machine_mode mode)
{
int regno;