/* SCRATCH must be shared because they represent distinct values. */
return;
case CLOBBER:
+ case CLOBBER_HIGH:
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
clobbers or clobbers of hard registers that originated as pseudos.
This is needed to allow safe register renaming. */
/* SCRATCH must be shared because they represent distinct values. */
return;
case CLOBBER:
+ case CLOBBER_HIGH:
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
clobbers or clobbers of hard registers that originated as pseudos.
This is needed to allow safe register renaming. */
case SIMPLE_RETURN:
return orig;
case CLOBBER:
+ case CLOBBER_HIGH:
/* Share clobbers of hard registers (like cc0), but do not share pseudo reg
clobbers or clobbers of hard registers that originated as pseudos.
This is needed to allow safe register renaming. */
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
}
+static GTY((deletable)) rtx
+hard_reg_clobbers_high[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+
+/* Return a CLOBBER_HIGH expression for register REGNO that clobbers MODE,
+ caching into HARD_REG_CLOBBERS_HIGH. */
+rtx
+gen_hard_reg_clobber_high (machine_mode mode, unsigned int regno)
+{
+ if (hard_reg_clobbers_high[mode][regno])
+ return hard_reg_clobbers_high[mode][regno];
+ else
+ return (hard_reg_clobbers_high[mode][regno]
+ = gen_rtx_CLOBBER_HIGH (VOIDmode, gen_rtx_REG (mode, regno)));
+}
+
location_t prologue_location;
location_t epilogue_location;
substituting any operand references appearing within. */
static void
-gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
+gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info)
{
RTX_CODE code;
int i;
for (i = 0; i < XVECLEN (x, 1); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
+ gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info);
}
printf (")");
return;
for (i = 0; i < XVECLEN (x, 2); i++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
+ gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info);
}
printf (")");
return;
case CLOBBER:
if (REG_P (XEXP (x, 0)))
{
- printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
- REGNO (XEXP (x, 0)));
+ printf ("gen_hard_reg_clobber (%smode, %i)",
+ GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+ REGNO (XEXP (x, 0)));
return;
}
break;
-
+ case CLOBBER_HIGH:
+ if (!REG_P (XEXP (x, 0)))
+ error ("CLOBBER_HIGH argument is not a register expr, at %s:%d",
+ info->loc.filename, info->loc.lineno);
+ printf ("gen_hard_reg_clobber_high (%smode, %i)",
+ GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+ REGNO (XEXP (x, 0)));
+ return;
+ break;
case CC0:
printf ("cc0_rtx");
return;
switch (fmt[i])
{
case 'e': case 'u':
- gen_exp (XEXP (x, i), subroutine_type, used);
+ gen_exp (XEXP (x, i), subroutine_type, used, info);
break;
case 'i':
for (j = 0; j < XVECLEN (x, i); j++)
{
printf (",\n\t\t");
- gen_exp (XVECEXP (x, i, j), subroutine_type, used);
+ gen_exp (XVECEXP (x, i, j), subroutine_type, used, info);
}
printf (")");
break;
becoming a separate instruction. USED is as for gen_exp. */
static void
-gen_emit_seq (rtvec vec, char *used)
+gen_emit_seq (rtvec vec, char *used, md_rtx_info *info)
{
for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i)
{
if (const char *name = get_emit_function (next))
{
printf (" %s (", name);
- gen_exp (next, DEFINE_EXPAND, used);
+ gen_exp (next, DEFINE_EXPAND, used, info);
printf (");\n");
if (!last_p && needs_barrier_p (next))
printf (" emit_barrier ();");
else
{
printf (" emit (");
- gen_exp (next, DEFINE_EXPAND, used);
+ gen_exp (next, DEFINE_EXPAND, used, info);
printf (", %s);\n", last_p ? "false" : "true");
}
}
for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
{
- if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
+ if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
+ && GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER_HIGH)
break;
if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
/* OLD and NEW_INSN are the same if both are to be a SCRATCH
of the same mode,
or if both are registers of the same mode and number. */
- if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
+ if (! (GET_CODE (old_rtx) == GET_CODE (new_rtx)
+ && GET_MODE (old_rtx) == GET_MODE (new_rtx)
&& ((GET_CODE (old_rtx) == MATCH_SCRATCH
&& GET_CODE (new_rtx) == MATCH_SCRATCH)
|| (REG_P (old_rtx) && REG_P (new_rtx)
? NULL
: XCNEWVEC (char, stats.num_generator_args));
printf (" return ");
- gen_exp (pattern, DEFINE_INSN, used);
+ gen_exp (pattern, DEFINE_INSN, used, info);
printf (";\n}\n\n");
XDELETEVEC (used);
}
&& XVECLEN (expand, 1) == 1)
{
printf (" return ");
- gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
+ gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info);
printf (";\n}\n\n");
return;
}
}
used = XCNEWVEC (char, stats.num_operand_vars);
- gen_emit_seq (XVEC (expand, 1), used);
+ gen_emit_seq (XVEC (expand, 1), used, info);
XDELETEVEC (used);
/* Call `get_insns' to extract the list of all the
printf (" (void) operand%d;\n", i);
}
- gen_emit_seq (XVEC (split, 2), used);
+ gen_emit_seq (XVEC (split, 2), used, info);
/* Call `get_insns' to make a list of all the
insns emitted within this gen_... function. */
the end of the vector. */
static void
-output_add_clobbers (void)
+output_add_clobbers (md_rtx_info *info)
{
struct clobber_pat *clobber;
struct clobber_ent *ent;
{
printf (" XVECEXP (pattern, 0, %d) = ", i);
gen_exp (XVECEXP (clobber->pattern, 1, i),
- GET_CODE (clobber->pattern), NULL);
+ GET_CODE (clobber->pattern), NULL, info);
printf (";\n");
}
/* Write out the routines to add CLOBBERs to a pattern and say whether they
clobber a hard reg. */
- output_add_clobbers ();
+ output_add_clobbers (&info);
output_added_clobbers_hard_reg_p ();
for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();