re PR target/42235 (redundant memory move from parameter space to spill space)
PR target/42235 * function.c (record_hard_reg_sets): New static function. (assign_parm_setup_reg): If an optab for extending exists and the generated code clobbbers no hard regs, emit the insn directly and create a REG_EQUIV note. From-SVN: r162240
This commit is contained in:
parent
f7587ed0d8
commit
71008de4b3
@ -1,3 +1,11 @@
|
||||
2010-07-16 Bernd Schmidt <bernds@codesourcery.com>
|
||||
|
||||
PR target/42235
|
||||
* function.c (record_hard_reg_sets): New static function.
|
||||
(assign_parm_setup_reg): If an optab for extending exists and the
|
||||
generated code clobbbers no hard regs, emit the insn directly and
|
||||
create a REG_EQUIV note.
|
||||
|
||||
2010-07-15 Nathan Froyd <froydnj@codesourcery.com>
|
||||
|
||||
* c-decl.c (detect_field_duplicates): Use DECL_CHAIN insted of
|
||||
|
@ -2854,6 +2854,21 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
|
||||
SET_DECL_RTL (parm, stack_parm);
|
||||
}
|
||||
|
||||
/* A subroutine of assign_parm_setup_reg, called through note_stores.
|
||||
This collects sets and clobbers of hard registers in a HARD_REG_SET,
|
||||
which is pointed to by DATA. */
|
||||
static void
|
||||
record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
|
||||
{
|
||||
HARD_REG_SET *pset = (HARD_REG_SET *)data;
|
||||
if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)];
|
||||
while (nregs-- > 0)
|
||||
SET_HARD_REG_BIT (*pset, REGNO (x) + nregs);
|
||||
}
|
||||
}
|
||||
|
||||
/* A subroutine of assign_parms. Allocate a pseudo to hold the current
|
||||
parameter. Get it there. Perform all ABI specified conversions. */
|
||||
|
||||
@ -2861,10 +2876,12 @@ static void
|
||||
assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
|
||||
struct assign_parm_data_one *data)
|
||||
{
|
||||
rtx parmreg;
|
||||
rtx parmreg, validated_mem;
|
||||
rtx equiv_stack_parm;
|
||||
enum machine_mode promoted_nominal_mode;
|
||||
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (parm));
|
||||
bool did_conversion = false;
|
||||
bool need_conversion, moved;
|
||||
|
||||
/* Store the parm in a pseudoregister during the function, but we may
|
||||
need to do it in a wider mode. Using 2 here makes the result
|
||||
@ -2893,11 +2910,16 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
|
||||
|
||||
/* Copy the value into the register, thus bridging between
|
||||
assign_parm_find_data_types and expand_expr_real_1. */
|
||||
if (data->nominal_mode != data->passed_mode
|
||||
|| promoted_nominal_mode != data->promoted_mode)
|
||||
{
|
||||
int save_tree_used;
|
||||
|
||||
equiv_stack_parm = data->stack_parm;
|
||||
validated_mem = validize_mem (data->entry_parm);
|
||||
|
||||
need_conversion = (data->nominal_mode != data->passed_mode
|
||||
|| promoted_nominal_mode != data->promoted_mode);
|
||||
moved = false;
|
||||
|
||||
if (need_conversion)
|
||||
{
|
||||
/* ENTRY_PARM has been converted to PROMOTED_MODE, its
|
||||
mode, by the caller. We now have to convert it to
|
||||
NOMINAL_MODE, if different. However, PARMREG may be in
|
||||
@ -2913,13 +2935,70 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
|
||||
|
||||
In addition, the conversion may involve a call, which could
|
||||
clobber parameters which haven't been copied to pseudo
|
||||
registers yet. Therefore, we must first copy the parm to
|
||||
a pseudo reg here, and save the conversion until after all
|
||||
registers yet.
|
||||
|
||||
First, we try to emit an insn which performs the necessary
|
||||
conversion. We verify that this insn does not clobber any
|
||||
hard registers. */
|
||||
|
||||
enum insn_code icode;
|
||||
rtx op0, op1;
|
||||
|
||||
icode = can_extend_p (promoted_nominal_mode, data->passed_mode,
|
||||
unsignedp);
|
||||
|
||||
op0 = parmreg;
|
||||
op1 = validated_mem;
|
||||
if (icode != CODE_FOR_nothing
|
||||
&& insn_data[icode].operand[0].predicate (op0, promoted_nominal_mode)
|
||||
&& insn_data[icode].operand[1].predicate (op1, data->passed_mode))
|
||||
{
|
||||
enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND;
|
||||
rtx insn, insns;
|
||||
HARD_REG_SET hardregs;
|
||||
|
||||
start_sequence ();
|
||||
insn = gen_extend_insn (op0, op1, promoted_nominal_mode,
|
||||
data->passed_mode, unsignedp);
|
||||
emit_insn (insn);
|
||||
insns = get_insns ();
|
||||
|
||||
moved = true;
|
||||
CLEAR_HARD_REG_SET (hardregs);
|
||||
for (insn = insns; insn && moved; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (INSN_P (insn))
|
||||
note_stores (PATTERN (insn), record_hard_reg_sets,
|
||||
&hardregs);
|
||||
if (!hard_reg_set_empty_p (hardregs))
|
||||
moved = false;
|
||||
}
|
||||
|
||||
end_sequence ();
|
||||
|
||||
if (moved)
|
||||
{
|
||||
emit_insn (insns);
|
||||
equiv_stack_parm = gen_rtx_fmt_e (code, GET_MODE (parmreg),
|
||||
equiv_stack_parm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (moved)
|
||||
/* Nothing to do. */
|
||||
;
|
||||
else if (need_conversion)
|
||||
{
|
||||
/* We did not have an insn to convert directly, or the sequence
|
||||
generated appeared unsafe. We must first copy the parm to a
|
||||
pseudo reg, and save the conversion until after all
|
||||
parameters have been moved. */
|
||||
|
||||
int save_tree_used;
|
||||
rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm));
|
||||
|
||||
emit_move_insn (tempreg, validize_mem (data->entry_parm));
|
||||
emit_move_insn (tempreg, validated_mem);
|
||||
|
||||
push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn);
|
||||
tempreg = convert_to_mode (data->nominal_mode, tempreg, unsignedp);
|
||||
@ -2949,7 +3028,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
|
||||
did_conversion = true;
|
||||
}
|
||||
else
|
||||
emit_move_insn (parmreg, validize_mem (data->entry_parm));
|
||||
emit_move_insn (parmreg, validated_mem);
|
||||
|
||||
/* If we were passed a pointer but the actual value can safely live
|
||||
in a register, put it in one. */
|
||||
@ -3034,7 +3113,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
|
||||
}
|
||||
else if ((set = single_set (linsn)) != 0
|
||||
&& SET_DEST (set) == parmreg)
|
||||
set_unique_reg_note (linsn, REG_EQUIV, data->stack_parm);
|
||||
set_unique_reg_note (linsn, REG_EQUIV, equiv_stack_parm);
|
||||
}
|
||||
|
||||
/* For pointer data type, suggest pointer register. */
|
||||
|
Loading…
Reference in New Issue
Block a user