[PR67753] fix copy of PARALLEL entry_parm to CONCAT target_reg

In assign_parms_setup_block, the copy of args in PARALLELs from
entry_parm to stack_parm is deferred to the parm conversion insn seq,
but the copy from stack_parm to target_reg was inserted in the normal
copy seq, that is executed before the conversion insn seq.  Oops.

We could do away with the need for an actual stack_parm in general,
which would have avoided the need for emitting the copy to target_reg
in the conversion seq, but at least on pa, due to the need for stack
to copy between SI and SF modes, it seems like using the reserved
stack slot is beneficial, so I put in logic to use a pre-reserved
stack slot when there is one, and emit the copy to target_reg in the
conversion seq if stack_parm was set up there.

for  gcc/ChangeLog

	PR rtl-optimization/67753
	PR rtl-optimization/64164
	* function.c (assign_parm_setup_block): Avoid allocating a
	stack slot if we don't have an ABI-reserved one.  Emit the
	copy to target_reg in the conversion seq if the copy from
	entry_parm is in it too.  Don't use the conversion seq to copy
	a PARALLEL to a REG or a CONCAT.

From-SVN: r229840
This commit is contained in:
Alexandre Oliva 2015-11-06 10:34:13 +00:00 committed by Alexandre Oliva
parent 5c661a4468
commit a029addda2
2 changed files with 44 additions and 5 deletions

View File

@ -1,3 +1,13 @@
2015-11-06 Alexandre Oliva <aoliva@redhat.com>
PR rtl-optimization/67753
PR rtl-optimization/64164
* function.c (assign_parm_setup_block): Avoid allocating a
stack slot if we don't have an ABI-reserved one. Emit the
copy to target_reg in the conversion seq if the copy from
entry_parm is in it too. Don't use the conversion seq to copy
a PARALLEL to a REG or a CONCAT.
2015-11-06 Richard Biener <rguenther@suse.de>
* tree-hash-traits.h (tree_operand_hash): Provide equal, not

View File

@ -2879,6 +2879,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
rtx entry_parm = data->entry_parm;
rtx stack_parm = data->stack_parm;
rtx target_reg = NULL_RTX;
bool in_conversion_seq = false;
HOST_WIDE_INT size;
HOST_WIDE_INT size_stored;
@ -2895,9 +2896,23 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
if (GET_CODE (reg) != CONCAT)
stack_parm = reg;
else
/* This will use or allocate a stack slot that we'd rather
avoid. FIXME: Could we avoid it in more cases? */
target_reg = reg;
{
target_reg = reg;
/* Avoid allocating a stack slot, if there isn't one
preallocated by the ABI. It might seem like we should
always prefer a pseudo, but converting between
floating-point and integer modes goes through the stack
on various machines, so it's better to use the reserved
stack slot than to risk wasting it and allocating more
for the conversion. */
if (stack_parm == NULL_RTX)
{
int save = generating_concat_p;
generating_concat_p = 0;
stack_parm = gen_reg_rtx (mode);
generating_concat_p = save;
}
}
data->stack_parm = NULL;
}
@ -2938,7 +2953,9 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
mem = validize_mem (copy_rtx (stack_parm));
/* Handle values in multiple non-contiguous locations. */
if (GET_CODE (entry_parm) == PARALLEL)
if (GET_CODE (entry_parm) == PARALLEL && !MEM_P (mem))
emit_group_store (mem, entry_parm, data->passed_type, size);
else if (GET_CODE (entry_parm) == PARALLEL)
{
push_to_sequence2 (all->first_conversion_insn,
all->last_conversion_insn);
@ -2946,6 +2963,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
all->first_conversion_insn = get_insns ();
all->last_conversion_insn = get_last_insn ();
end_sequence ();
in_conversion_seq = true;
}
else if (size == 0)
@ -3025,11 +3043,22 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
all->first_conversion_insn = get_insns ();
all->last_conversion_insn = get_last_insn ();
end_sequence ();
in_conversion_seq = true;
}
if (target_reg)
{
emit_move_insn (target_reg, stack_parm);
if (!in_conversion_seq)
emit_move_insn (target_reg, stack_parm);
else
{
push_to_sequence2 (all->first_conversion_insn,
all->last_conversion_insn);
emit_move_insn (target_reg, stack_parm);
all->first_conversion_insn = get_insns ();
all->last_conversion_insn = get_last_insn ();
end_sequence ();
}
stack_parm = target_reg;
}