参照元†
返り値†
/* Final change of pseudos got hard registers into the corresponding
hard registers and removing temporary clobbers. */
void
lra_final_code_change (void)
{
int i, hard_regno;
basic_block bb;
rtx_insn *insn, *curr;
int max_regno = max_reg_num ();
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (lra_reg_info[i].nrefs != 0
&& (hard_regno = lra_get_regno_hard_regno (i)) >= 0)
SET_REGNO (regno_reg_rtx[i], hard_regno);
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS_SAFE (bb, insn, curr)
if (INSN_P (insn))
{
rtx pat = PATTERN (insn);
if (GET_CODE (pat) == CLOBBER && LRA_TEMP_CLOBBER_P (pat))
{
/* Remove clobbers temporarily created in LRA. We don't
need them anymore and don't want to waste compiler
time processing them in a few subsequent passes. */
lra_invalidate_insn_data (insn);
delete_insn (insn);
continue;
}
/* IRA can generate move insns involving pseudos. It is
better remove them earlier to speed up compiler a bit.
It is also better to do it here as they might not pass
final RTL check in LRA, (e.g. insn moving a control
register into itself). So remove an useless move insn
unless next insn is USE marking the return reg (we should
save this as some subsequent optimizations assume that
such original insns are saved). */
if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET
&& REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat))
&& REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat))
&& (! return_regno_p (REGNO (SET_SRC (pat)))
|| ! regno_in_use_p (insn, REGNO (SET_SRC (pat)))))
{
lra_invalidate_insn_data (insn);
delete_insn (insn);
continue;
}
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
struct lra_insn_reg *reg;
for (reg = id->regs; reg != NULL; reg = reg->next)
if (reg->regno >= FIRST_PSEUDO_REGISTER
&& lra_reg_info [reg->regno].nrefs == 0)
break;
if (reg != NULL)
{
/* Pseudos still can be in debug insns in some very rare
and complicated cases, e.g. the pseudo was removed by
inheritance and the debug insn is not EBBs where the
inheritance happened. It is difficult and time
consuming to find what hard register corresponds the
pseudo -- so just remove the debug insn. Another
solution could be assigning hard reg/memory but it
would be a misleading info. It is better not to have
info than have it wrong. */
lra_assert (DEBUG_INSN_P (insn));
lra_invalidate_insn_data (insn);
delete_insn (insn);
continue;
}
struct lra_static_insn_data *static_id = id->insn_static_data;
bool insn_change_p = false;
for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
if ((DEBUG_INSN_P (insn) || ! static_id->operand[i].is_operator)
&& alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
{
lra_update_dup (id, i);
insn_change_p = true;
}
if (insn_change_p)
lra_update_operator_dups (id);
}
}
コメント†