aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2015-11-06 10:34:13 +0000
committerAlexandre Oliva <aoliva@gcc.gnu.org>2015-11-06 10:34:13 +0000
commita029addda261d1f212ee33d0cae9fd1f67a5fa8d (patch)
tree2c721a902fe8f0e45fb9a2ad6540cd633ecc1158
parent5c661a44685cb5b0185c5a81c26f41dc2876e9df (diff)
downloadgcc-a029addda261d1f212ee33d0cae9fd1f67a5fa8d.zip
gcc-a029addda261d1f212ee33d0cae9fd1f67a5fa8d.tar.gz
gcc-a029addda261d1f212ee33d0cae9fd1f67a5fa8d.tar.bz2
[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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/function.c39
2 files changed, 44 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e7c82e6..ae2c5cf 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/function.c b/gcc/function.c
index 0d7cabc..a637cb3 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -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;
}