static rtx simplify_shift_const_1 (enum rtx_code, machine_mode, rtx, int);
static rtx simplify_shift_const (rtx, enum rtx_code, machine_mode, rtx,
int);
-static int recog_for_combine (rtx *, rtx_insn *, rtx *);
+static int recog_for_combine (rtx *, rtx_insn *, rtx *, unsigned = 0, unsigned = 0);
static rtx gen_lowpart_for_combine (machine_mode, rtx);
static enum rtx_code simplify_compare_const (enum rtx_code, machine_mode,
rtx *, rtx *);
/* Try to split PATTERN found in INSN. This returns NULL_RTX if
PATTERN cannot be split. Otherwise, it returns an insn sequence.
+ Updates OLD_NREGS with the max number of regs before the split
+ and NEW_NREGS after the split.
This is a wrapper around split_insns which ensures that the
reg_stat vector is made larger if the splitter creates a new
register. */
static rtx_insn *
-combine_split_insns (rtx pattern, rtx_insn *insn)
+combine_split_insns (rtx pattern, rtx_insn *insn,
+ unsigned int *old_nregs,
+ unsigned int *new_regs)
{
rtx_insn *ret;
unsigned int nregs;
-
+ *old_nregs = max_reg_num ();
ret = split_insns (pattern, insn);
- nregs = max_reg_num ();
+ *new_regs = nregs = max_reg_num ();
if (nregs > reg_stat.length ())
reg_stat.safe_grow_cleared (nregs, true);
return ret;
{
rtx parallel, *split;
rtx_insn *m_split_insn;
+ unsigned int old_nregs, new_nregs;
/* See if the MD file can split NEWPAT. If it can't, see if letting it
use I2DEST as a scratch register will help. In the latter case,
convert I2DEST to the mode of the source of NEWPAT if we can. */
- m_split_insn = combine_split_insns (newpat, i3);
+ m_split_insn = combine_split_insns (newpat, i3, &old_nregs, &new_nregs);
/* We can only use I2DEST as a scratch reg if it doesn't overlap any
inputs of NEWPAT. */
gen_rtvec (2, newpat,
gen_rtx_CLOBBER (VOIDmode,
i2dest)));
- m_split_insn = combine_split_insns (parallel, i3);
+ m_split_insn = combine_split_insns (parallel, i3, &old_nregs, &new_nregs);
/* If that didn't work, try changing the mode of I2DEST if
we can. */
gen_rtvec (2, newpat,
gen_rtx_CLOBBER (VOIDmode,
ni2dest))));
- m_split_insn = combine_split_insns (parallel, i3);
+ m_split_insn = combine_split_insns (parallel, i3, &old_nregs, &new_nregs);
if (m_split_insn == 0
&& REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
if (m_split_insn == 0 && newpat_vec_with_clobbers)
{
parallel = gen_rtx_PARALLEL (VOIDmode, newpat_vec_with_clobbers);
- m_split_insn = combine_split_insns (parallel, i3);
+ m_split_insn = combine_split_insns (parallel, i3, &old_nregs, &new_nregs);
}
if (m_split_insn && NEXT_INSN (m_split_insn) == NULL_RTX)
{
rtx m_split_pat = PATTERN (m_split_insn);
- insn_code_number = recog_for_combine (&m_split_pat, i3, &new_i3_notes);
+ insn_code_number = recog_for_combine (&m_split_pat, i3, &new_i3_notes,
+ old_nregs, new_nregs);
if (insn_code_number >= 0)
newpat = m_split_pat;
}
&& (next_nonnote_nondebug_insn (i2) == i3
|| ! reg_used_between_p (SET_DEST (i2set), i2, i3)))
insn_code_number = recog_for_combine (&newi3pat, i3,
- &new_i3_notes);
+ &new_i3_notes,
+ old_nregs, new_nregs);
if (insn_code_number >= 0)
newpat = newi3pat;
MEM_ADDR_SPACE (x)))
{
rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
+ unsigned int old_nregs, new_nregs;
rtx_insn *seq = combine_split_insns (gen_rtx_SET (reg, XEXP (x, 0)),
- subst_insn);
+ subst_insn, &old_nregs, &new_nregs);
/* This should have produced two insns, each of which sets our
placeholder. If the source of the second is a valid address,
return value. */
static int
-recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
+recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes,
+ unsigned old_nregs, unsigned new_nregs)
{
rtx pat = *pnewpat;
rtx pat_without_clobbers;
if (insn_code_number >= 0
&& insn_code_number != NOOP_MOVE_INSN_CODE)
{
+ /* Create the reg dead notes if needed for the regs that were created via split. */
+ for (; old_nregs < new_nregs; old_nregs++)
+ notes = alloc_reg_note (REG_DEAD, regno_reg_rtx[old_nregs], notes);
old_pat = PATTERN (insn);
old_notes = REG_NOTES (insn);
old_icode = INSN_CODE (insn);
PNOTES is a pointer to a location where any REG_UNUSED notes added for
the CLOBBERs are placed.
+ If OLD_NREGS != NEW_NREGS, then PNOTES also includes REG_DEAD notes added.
The value is the final insn code from the pattern ultimately matched,
or -1. */
static int
-recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
+recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes,
+ unsigned int old_nregs, unsigned int new_nregs)
{
rtx pat = *pnewpat;
- int insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes);
+ int insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes,
+ old_nregs, new_nregs);
if (insn_code_number >= 0 || check_asm_operands (pat))
return insn_code_number;
if (changed)
{
- insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes);
+ insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes,
+ old_nregs, new_nregs);
if (insn_code_number < 0)
undo_to_marker (marker);