: (FIXED_REGNO_P (REGNO (X)) \
&& REGNO_REG_CLASS (REGNO (X)) != NO_REGS) ? 0 \
: 2) \
- : rtx_cost (X) * 2) \
+ : rtx_cost (X, SET) * 2)
/* Determine if the quantity number for register X represents a valid index
into the `qty_...' variables. */
#define COSTS_N_INSNS(N) ((N) * 4 - 2)
int
-rtx_cost (x)
+rtx_cost (x, outer_code)
rtx x;
+ enum rtx_code outer_code;
{
register int i, j;
register enum rtx_code code;
+ GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
return 2;
#ifdef RTX_COSTS
- RTX_COSTS (x, code);
+ RTX_COSTS (x, code, outer_code);
#endif
- CONST_COSTS (x, code);
+ CONST_COSTS (x, code, outer_code);
}
/* Sum the costs of the sub-rtx's, plus cost of this operation,
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
if (fmt[i] == 'e')
- total += rtx_cost (XEXP (x, i));
+ total += rtx_cost (XEXP (x, i), code);
else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++)
- total += rtx_cost (XVECEXP (x, i, j));
+ total += rtx_cost (XVECEXP (x, i, j), code);
return total;
}
register int changed = 0;
if (x == 0)
- return;
+ return 0;
code = GET_CODE (x);
if (code == REG)
&& (new = lookup_as_function (x, CONST_INT)) != 0)
return new;
+ /* If this is a paradoxical SUBREG, we can't do anything with
+ it because we have no idea what value the extra bits would have. */
+ if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ return x;
+
/* Fold SUBREG_REG. If it changed, see if we can simplify the SUBREG.
We might be able to if the SUBREG is extracting a single word in an
integral mode or extracting the low part. */
if (new)
return new;
}
+
+ /* If this is a narrowing SUBREG and our operand is a REG, see if
+ we can find an equivalence for REG that is a arithmetic operation
+ in a wider mode where both operands are paradoxical SUBREGs
+ from objects of our result mode. In that case, we couldn't report
+ an equivalent value for that operation, since we don't know what the
+ extra bits will be. But we can find an equivalence for this SUBREG
+ by folding that operation is the narrow mode. This allows us to
+ fold arithmetic in narrow modes when the machine only supports
+ word-sized arithmetic. */
+
+ if (GET_CODE (folded_arg0) == REG
+ && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0)))
+ {
+ struct table_elt *elt;
+
+ /* We can use HASH here since we know that canon_hash won't be
+ called. */
+ elt = lookup (folded_arg0,
+ HASH (folded_arg0, GET_MODE (folded_arg0)),
+ GET_MODE (folded_arg0));
+
+ if (elt)
+ elt = elt->first_same_value;
+
+ for (; elt; elt = elt->next_same_value)
+ {
+ /* Just check for unary and binary operations. */
+ if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1'
+ && GET_CODE (elt->exp) != SIGN_EXTEND
+ && GET_CODE (elt->exp) != ZERO_EXTEND
+ && GET_CODE (XEXP (elt->exp, 0)) == SUBREG
+ && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode)
+ {
+ rtx op0 = SUBREG_REG (XEXP (elt->exp, 0));
+
+ if (GET_CODE (op0) != REG && ! CONSTANT_P (op0))
+ op0 = fold_rtx (op0, 0);
+
+ op0 = equiv_constant (op0);
+ if (op0)
+ new = simplify_unary_operation (GET_CODE (elt->exp), mode,
+ op0, mode);
+ }
+ else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2'
+ || GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c')
+ && ((GET_CODE (XEXP (elt->exp, 0)) == SUBREG
+ && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 0)))
+ == mode))
+ || CONSTANT_P (XEXP (elt->exp, 0)))
+ && ((GET_CODE (XEXP (elt->exp, 1)) == SUBREG
+ && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 1)))
+ == mode))
+ || CONSTANT_P (XEXP (elt->exp, 1))))
+ {
+ rtx op0 = gen_lowpart_common (mode, XEXP (elt->exp, 0));
+ rtx op1 = gen_lowpart_common (mode, XEXP (elt->exp, 1));
+
+ if (op0 && GET_CODE (op0) != REG && ! CONSTANT_P (op0))
+ op0 = fold_rtx (op0, 0);
+
+ if (op0)
+ op0 = equiv_constant (op0);
+
+ if (op1 && GET_CODE (op1) != REG && ! CONSTANT_P (op1))
+ op1 = fold_rtx (op1, 0);
+
+ if (op1)
+ op1 = equiv_constant (op1);
+
+ if (op0 && op1)
+ new = simplify_binary_operation (GET_CODE (elt->exp), mode,
+ op0, op1);
+ }
+
+ if (new)
+ return new;
+ }
+ }
+
return x;
case NOT:
struct clobber_pat
{
- int code_number; /* Counts only insns. */
+ struct clobber_ent *insns;
rtx pattern;
int first_clobber;
struct clobber_pat *next;
} *clobber_list;
+/* Records one insn that uses the clobber list. */
+
+struct clobber_ent
+{
+ int code_number; /* Counts only insns. */
+ struct clobber_ent *next;
+};
+
static void
max_operand_1 (x)
rtx x;
if (i != XVECLEN (insn, 1) - 1)
{
- register struct clobber_pat *new
- = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
+ register struct clobber_pat *p;
+ register struct clobber_ent *link
+ = (struct clobber_ent *) xmalloc (sizeof (struct clobber_ent));
+ register int j;
+
+ link->code_number = insn_code_number;
+
+ /* See if any previous CLOBBER_LIST entry is the same as this
+ one. */
+
+ for (p = clobber_list; p; p = p->next)
+ {
+ if (p->first_clobber != i + 1
+ || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
+ continue;
+
+ for (j = i + 1; j < XVECLEN (insn, 1); j++)
+ {
+ rtx old = XEXP (XVECEXP (p->pattern, 1, j), 0);
+ rtx new = XEXP (XVECEXP (insn, 1, j), 0);
+
+ /* OLD and NEW are the same if both are to be a SCRATCH
+ or if both are registers of the same mode and number. */
+ if (! ((GET_CODE (old) == MATCH_SCRATCH
+ && GET_CODE (new) == MATCH_SCRATCH)
+ || (GET_CODE (old) == REG && GET_CODE (new) == REG
+ && GET_MODE (old) == GET_MODE (new)
+ && REGNO (old) == REGNO (new))))
+ break;
+ }
+
+ if (j == XVECLEN (insn, 1))
+ break;
+ }
+
+ if (p == 0)
+ {
+ p = (struct clobber_pat *) xmalloc (sizeof (struct clobber_pat));
- new->code_number = insn_code_number;
- new->pattern = insn;
- new->first_clobber = i + 1;
- new->next = clobber_list;
- clobber_list = new;
+ p->insns = 0;
+ p->pattern = insn;
+ p->first_clobber = i + 1;
+ p->next = clobber_list;
+ clobber_list = p;
+ }
+
+ link->next = p->insns;
+ p->insns = link;
}
}
output_add_clobbers ()
{
struct clobber_pat *clobber;
+ struct clobber_ent *ent;
int i;
printf ("\n\nvoid\nadd_clobbers (pattern, insn_code_number)\n");
for (clobber = clobber_list; clobber; clobber = clobber->next)
{
- printf (" case %d:\n", clobber->code_number);
+ for (ent = clobber->insns; ent; ent = ent->next)
+ printf (" case %d:\n", ent->code_number);
for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
{
printf (";\n");
}
- printf (" break;\n");
+ printf (" break;\n\n");
}
printf (" default:\n");