/* Register renaming for the GNU compiler.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
/* See whether it accepts all modes that occur in
definition and uses. */
for (tmp = this; tmp; tmp = tmp->next_use)
- if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc)))
+ if (! HARD_REGNO_MODE_OK (new_reg, GET_MODE (*tmp->loc))
+ || (tmp->need_caller_save_reg
+ && ! (HARD_REGNO_CALL_PART_CLOBBERED
+ (reg, GET_MODE (*tmp->loc)))
+ && (HARD_REGNO_CALL_PART_CLOBBERED
+ (new_reg, GET_MODE (*tmp->loc)))))
break;
if (! tmp)
{
case CONST:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case SYMBOL_REF:
case LABEL_REF:
case CC0:
rtx note;
rtx old_operands[MAX_RECOG_OPERANDS];
rtx old_dups[MAX_DUP_OPERANDS];
- int i;
+ int i, icode;
int alt;
int predicated;
(6) For any write we find in an operand, make a new chain.
(7) For any REG_UNUSED, close any chains we just opened. */
+ icode = recog_memoized (insn);
extract_insn (insn);
- constrain_operands (1);
+ if (! constrain_operands (1))
+ fatal_insn_not_found (insn);
preprocess_constraints ();
alt = which_alternative;
n_ops = recog_data.n_operands;
}
for (i = 0; i < recog_data.n_dups; i++)
{
+ int dup_num = recog_data.dup_num[i];
+
old_dups[i] = *recog_data.dup_loc[i];
*recog_data.dup_loc[i] = cc0_rtx;
+
+ /* For match_dup of match_operator or match_parallel, share
+ them, so that we don't miss changes in the dup. */
+ if (icode >= 0
+ && insn_data[icode].operand[dup_num].eliminable == 0)
+ old_dups[i] = recog_data.operand[dup_num];
}
scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
rtx x;
struct value_data *vd;
{
+ /* SUBREGS are supposed to have been eliminated by now. But some
+ ports, e.g. i386 sse, use them to smuggle vector type information
+ through to instruction selection. Each such SUBREG should simplify,
+ so if we get a NULL we've done something wrong elsewhere. */
+
+ if (GET_CODE (x) == SUBREG)
+ x = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
+ GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
if (REG_P (x))
{
unsigned int regno = REGNO (x);
{
if (vd->e[j].mode == VOIDmode)
continue;
- n = HARD_REGNO_NREGS (regno, vd->e[j].mode);
+ n = HARD_REGNO_NREGS (j, vd->e[j].mode);
if (j + n > regno)
for (i = 0; i < n; ++i)
kill_value_regno (j + i, vd);
void *data;
{
struct value_data *vd = data;
- if (GET_CODE (set) != CLOBBER && REG_P (x))
+ if (GET_CODE (set) != CLOBBER)
{
kill_value (x, vd);
- set_value_regno (REGNO (x), GET_MODE (x), vd);
+ if (REG_P (x))
+ set_value_regno (REGNO (x), GET_MODE (x), vd);
}
}
if (vd->e[sr].mode == VOIDmode)
set_value_regno (sr, vd->e[dr].mode, vd);
+ /* If SRC had been assigned a mode narrower than the copy, we can't
+ link DEST into the chain, because not all of the pieces of the
+ copy came from oldest_regno. */
+ else if (sn > (unsigned int) HARD_REGNO_NREGS (sr, vd->e[sr].mode))
+ return;
+
/* Link DR at the end of the value chain used by SR. */
vd->e[dr].oldest_regno = vd->e[sr].oldest_regno;
for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
if (TEST_HARD_REG_BIT (reg_class_contents[class], i)
&& (vd->e[i].mode == mode
- || mode_change_ok (vd->e[i].mode, mode, regno)))
+ || mode_change_ok (vd->e[i].mode, mode, i)))
{
- rtx new = gen_rtx_REG (mode, i);
+ rtx new = gen_rtx_raw_REG (mode, i);
ORIGINAL_REGNO (new) = ORIGINAL_REGNO (reg);
return new;
}
set = single_set (insn);
extract_insn (insn);
- constrain_operands (1);
+ if (! constrain_operands (1))
+ fatal_insn_not_found (insn);
preprocess_constraints ();
alt = which_alternative;
n_ops = recog_data.n_operands;
/* Otherwise, try all valid registers and see if its valid. */
for (i = vd->e[regno].oldest_regno; i != regno;
i = vd->e[i].next_regno)
- if (mode == vd->e[regno].mode)
+ if (vd->e[i].mode == mode
+ || mode_change_ok (vd->e[i].mode, mode, i))
{
- new = gen_rtx_REG (mode, i);
+ new = gen_rtx_raw_REG (mode, i);
if (validate_change (insn, &SET_SRC (set), new, 0))
{
ORIGINAL_REGNO (new) = ORIGINAL_REGNO (src);