+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
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;
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;
}
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);
all->first_conversion_insn = get_insns ();
all->last_conversion_insn = get_last_insn ();
end_sequence ();
+ in_conversion_seq = true;
}
else if (size == 0)
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;
}