function.c (assign_parm_remove_parallels): New.
authorDaniel Jacobowitz <dan@codesourcery.com>
Tue, 1 Jul 2008 20:49:40 +0000 (20:49 +0000)
committerDaniel Jacobowitz <drow@gcc.gnu.org>
Tue, 1 Jul 2008 20:49:40 +0000 (20:49 +0000)
* 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

gcc/ChangeLog
gcc/function.c

index 1e258ac1739df40e1f3794e46d97c39510852b9e..01ed439fdcf45801c1b2f84f63d93aa3e626c844 100644 (file)
@@ -1,3 +1,12 @@
+2008-07-01  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * 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.
+
 2008-07-01  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * c-typeck.c (convert_for_assignment): Use
index 680b36048599e1cca609fb334f00d78965e614e7..d8234da38771098f5e4d8963832234d56d84ebef 100644 (file)
@@ -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.  */