aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@codesourcery.com>2008-07-01 20:49:40 +0000
committerDaniel Jacobowitz <drow@gcc.gnu.org>2008-07-01 20:49:40 +0000
commit4d2a9850cf9af014fd058118ecc8eafa72456f30 (patch)
tree1aa92657c6dd16fdbe1442fbe6606da02e7eed9f /gcc/function.c
parentf83c7f631f959a5c1189527e90c065b68cdacd4d (diff)
downloadgcc-4d2a9850cf9af014fd058118ecc8eafa72456f30.zip
gcc-4d2a9850cf9af014fd058118ecc8eafa72456f30.tar.gz
gcc-4d2a9850cf9af014fd058118ecc8eafa72456f30.tar.bz2
function.c (assign_parm_remove_parallels): New.
* function.c (assign_parm_remove_parallels): New. (assign_parm_setup_block_p): Do not return true for non-BLKmode PARALLELs. (assign_parm_setup_block): Do not handle them. (assign_parm_setup_reg, assign_parm_setup_stack): Call assign_parm_remove_parallels. From-SVN: r137326
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c79
1 files changed, 28 insertions, 51 deletions
diff --git a/gcc/function.c b/gcc/function.c
index 680b360..d8234da3 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -2352,6 +2352,30 @@ assign_parm_adjust_entry_rtl (struct assign_parm_data_one *data)
data->entry_parm = entry_parm;
}
+/* A subroutine of assign_parms. Reconstitute any values which were
+ passed in multiple registers and would fit in a single register. */
+
+static void
+assign_parm_remove_parallels (struct assign_parm_data_one *data)
+{
+ rtx entry_parm = data->entry_parm;
+
+ /* Convert the PARALLEL to a REG of the same mode as the parallel.
+ This can be done with register operations rather than on the
+ stack, even if we will store the reconstituted parameter on the
+ stack later. */
+ if (GET_CODE (entry_parm) == PARALLEL
+ && data->passed_mode != BLKmode)
+ {
+ rtx parmreg = gen_reg_rtx (GET_MODE (entry_parm));
+ emit_group_store (parmreg, entry_parm, NULL_TREE,
+ GET_MODE_SIZE (GET_MODE (entry_parm)));
+ entry_parm = parmreg;
+ }
+
+ data->entry_parm = entry_parm;
+}
+
/* A subroutine of assign_parms. Adjust DATA->STACK_RTL such that it's
always valid and properly aligned. */
@@ -2397,8 +2421,6 @@ assign_parm_setup_block_p (struct assign_parm_data_one *data)
{
if (data->nominal_mode == BLKmode)
return true;
- if (GET_CODE (data->entry_parm) == PARALLEL)
- return true;
#ifdef BLOCK_REG_PADDING
/* Only assign_parm_setup_block knows how to deal with register arguments
@@ -2424,59 +2446,10 @@ assign_parm_setup_block (struct assign_parm_data_all *all,
rtx stack_parm = data->stack_parm;
HOST_WIDE_INT size;
HOST_WIDE_INT size_stored;
- rtx orig_entry_parm = entry_parm;
if (GET_CODE (entry_parm) == PARALLEL)
entry_parm = emit_group_move_into_temps (entry_parm);
- /* If we've a non-block object that's nevertheless passed in parts,
- reconstitute it in register operations rather than on the stack. */
- if (GET_CODE (entry_parm) == PARALLEL
- && data->nominal_mode != BLKmode)
- {
- rtx elt0 = XEXP (XVECEXP (orig_entry_parm, 0, 0), 0);
-
- if ((XVECLEN (entry_parm, 0) > 1
- || hard_regno_nregs[REGNO (elt0)][GET_MODE (elt0)] > 1)
- && use_register_for_decl (parm))
- {
- rtx parmreg = gen_reg_rtx (data->nominal_mode);
-
- push_to_sequence2 (all->first_conversion_insn,
- all->last_conversion_insn);
-
- /* For values returned in multiple registers, handle possible
- incompatible calls to emit_group_store.
-
- For example, the following would be invalid, and would have to
- be fixed by the conditional below:
-
- emit_group_store ((reg:SF), (parallel:DF))
- emit_group_store ((reg:SI), (parallel:DI))
-
- An example of this are doubles in e500 v2:
- (parallel:DF (expr_list (reg:SI) (const_int 0))
- (expr_list (reg:SI) (const_int 4))). */
- if (data->nominal_mode != data->passed_mode)
- {
- rtx t = gen_reg_rtx (GET_MODE (entry_parm));
- emit_group_store (t, entry_parm, NULL_TREE,
- GET_MODE_SIZE (GET_MODE (entry_parm)));
- convert_move (parmreg, t, 0);
- }
- else
- emit_group_store (parmreg, entry_parm, data->nominal_type,
- int_size_in_bytes (data->nominal_type));
-
- all->first_conversion_insn = get_insns ();
- all->last_conversion_insn = get_last_insn ();
- end_sequence ();
-
- SET_DECL_RTL (parm, parmreg);
- return;
- }
- }
-
size = int_size_in_bytes (data->passed_type);
size_stored = CEIL_ROUND (size, UNITS_PER_WORD);
if (stack_parm == 0)
@@ -2641,6 +2614,8 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
else
SET_DECL_RTL (parm, parmreg);
+ assign_parm_remove_parallels (data);
+
/* Copy the value into the register. */
if (data->nominal_mode != data->passed_mode
|| promoted_nominal_mode != data->promoted_mode)
@@ -2803,6 +2778,8 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm,
execution. */
bool to_conversion = false;
+ assign_parm_remove_parallels (data);
+
if (data->promoted_mode != data->nominal_mode)
{
/* Conversion is required. */