OSDN Git Service

* calls.c (precompute_register_parameters): Force all PARALLELs
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Nov 2004 06:22:56 +0000 (06:22 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Nov 2004 06:22:56 +0000 (06:22 +0000)
        into pseudo registers.
        (load_register_parameters): Copy PARALLELs into hard registers.
        * function.c (assign_parm_setup_block): Copy PARALLELS into
        pseudo registers.  Do emit_group_store in conversion_insns.
        * expr.c (emit_group_load_1): Rename from emit_group_load, take
        tmps as an argument.  Move final copy loop ...
        (emit_group_load): ... here.  New function.
        (emit_group_load_into_temps, emit_group_move_into_temps): New.
        * expr.h: Declare them.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@90613 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/calls.c
gcc/expr.c
gcc/expr.h
gcc/function.c

index de89cb0..82ca433 100644 (file)
@@ -1,3 +1,16 @@
+2004-11-13  Richard Henderson  <rth@redhat.com>
+
+       * calls.c (precompute_register_parameters): Force all PARALLELs
+       into pseudo registers.
+       (load_register_parameters): Copy PARALLELs into hard registers.
+       * function.c (assign_parm_setup_block): Copy PARALLELS into
+       pseudo registers.  Do emit_group_store in conversion_insns.
+       * expr.c (emit_group_load_1): Rename from emit_group_load, take
+       tmps as an argument.  Move final copy loop ...
+       (emit_group_load): ... here.  New function.
+       (emit_group_load_into_temps, emit_group_move_into_temps): New.
+       * expr.h: Declare them.
+
 2004-11-14  Kazu Hirata  <kazu@cs.umass.edu>
 
        * tree-cfg.c, tree-if-conv.c, tree-ssa-loop-ivopts.c,
index cfcf01c..e66181e 100644 (file)
@@ -644,7 +644,8 @@ call_expr_flags (tree t)
    Set REG_PARM_SEEN if we encounter a register parameter.  */
 
 static void
-precompute_register_parameters (int num_actuals, struct arg_data *args, int *reg_parm_seen)
+precompute_register_parameters (int num_actuals, struct arg_data *args,
+                               int *reg_parm_seen)
 {
   int i;
 
@@ -679,6 +680,17 @@ precompute_register_parameters (int num_actuals, struct arg_data *args, int *reg
                             TYPE_MODE (TREE_TYPE (args[i].tree_value)),
                             args[i].value, args[i].unsignedp);
 
+       /* If we're going to have to load the value by parts, pull the
+          parts into pseudos.  The part extraction process can involve
+          non-trivial computation.  */
+       if (GET_CODE (args[i].reg) == PARALLEL)
+         {
+           tree type = TREE_TYPE (args[i].tree_value);
+           args[i].value
+             = emit_group_load_into_temps (args[i].reg, args[i].value,
+                                           type, int_size_in_bytes (type));
+         }
+
        /* If the value is expensive, and we are inside an appropriately
           short loop, put the value into a pseudo and then put the pseudo
           into the hard reg.
@@ -687,13 +699,13 @@ precompute_register_parameters (int num_actuals, struct arg_data *args, int *reg
           register parameters.  This is to avoid reload conflicts while
           loading the parameters registers.  */
 
-       if ((! (REG_P (args[i].value)
-               || (GET_CODE (args[i].value) == SUBREG
-                   && REG_P (SUBREG_REG (args[i].value)))))
-           && args[i].mode != BLKmode
-           && rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
-           && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
-               || optimize))
+       else if ((! (REG_P (args[i].value)
+                    || (GET_CODE (args[i].value) == SUBREG
+                        && REG_P (SUBREG_REG (args[i].value)))))
+                && args[i].mode != BLKmode
+                && rtx_cost (args[i].value, SET) > COSTS_N_INSNS (1)
+                && ((SMALL_REGISTER_CLASSES && *reg_parm_seen)
+                    || optimize))
          args[i].value = copy_to_mode_reg (args[i].mode, args[i].value);
       }
 }
@@ -1454,11 +1466,7 @@ load_register_parameters (struct arg_data *args, int num_actuals,
             locations.  The Irix 6 ABI has examples of this.  */
 
          if (GET_CODE (reg) == PARALLEL)
-           {
-             tree type = TREE_TYPE (args[i].tree_value);
-             emit_group_load (reg, args[i].value, type,
-                              int_size_in_bytes (type));
-           }
+           emit_group_move (reg, args[i].value);
 
          /* If simple case, just do move.  If normal partial, store_one_arg
             has already loaded the register for us.  In all other cases,
index 6037fd1..59da4fd 100644 (file)
@@ -1557,15 +1557,14 @@ gen_group_rtx (rtx orig)
   return gen_rtx_PARALLEL (GET_MODE (orig), gen_rtvec_v (length, tmps));
 }
 
-/* Emit code to move a block ORIG_SRC of type TYPE to a block DST,
-   where DST is non-consecutive registers represented by a PARALLEL.
-   SSIZE represents the total size of block ORIG_SRC in bytes, or -1
-   if not known.  */
+/* A subroutine of emit_group_load.  Arguments as for emit_group_load,
+   except that values are placed in TMPS[i], and must later be moved
+   into corrosponding XEXP (XVECEXP (DST, 0, i), 0) element.  */
 
-void
-emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
+static void
+emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
 {
-  rtx *tmps, src;
+  rtx src;
   int start, i;
   enum machine_mode m = GET_MODE (orig_src);
 
@@ -1585,7 +1584,7 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
       /* ...and back again.  */
       if (imode != BLKmode)
        src = gen_lowpart (imode, src);
-      emit_group_load (dst, src, type, ssize);
+      emit_group_load_1 (tmps, dst, src, type, ssize);
       return;
     }
 
@@ -1596,8 +1595,6 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
   else
     start = 1;
 
-  tmps = alloca (sizeof (rtx) * XVECLEN (dst, 0));
-
   /* Process the pieces.  */
   for (i = start; i < XVECLEN (dst, 0); i++)
     {
@@ -1709,10 +1706,61 @@ emit_group_load (rtx dst, rtx orig_src, tree type ATTRIBUTE_UNUSED, int ssize)
        tmps[i] = expand_shift (LSHIFT_EXPR, mode, tmps[i],
                                build_int_cst (NULL_TREE, shift), tmps[i], 0);
     }
+}
+
+/* Emit code to move a block SRC of type TYPE to a block DST,
+   where DST is non-consecutive registers represented by a PARALLEL.
+   SSIZE represents the total size of block ORIG_SRC in bytes, or -1
+   if not known.  */
+
+void
+emit_group_load (rtx dst, rtx src, tree type, int ssize)
+{
+  rtx *tmps;
+  int i;
+
+  tmps = alloca (sizeof (rtx) * XVECLEN (dst, 0));
+  emit_group_load_1 (tmps, dst, src, type, ssize);
 
   /* Copy the extracted pieces into the proper (probable) hard regs.  */
-  for (i = start; i < XVECLEN (dst, 0); i++)
-    emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
+  for (i = 0; i < XVECLEN (dst, 0); i++)
+    {
+      rtx d = XEXP (XVECEXP (dst, 0, i), 0);
+      if (d == NULL)
+       continue;
+      emit_move_insn (d, tmps[i]);
+    }
+}
+
+/* Similar, but load SRC into new pseudos in a format that looks like
+   PARALLEL.  This can later be fed to emit_group_move to get things
+   in the right place.  */
+
+rtx
+emit_group_load_into_temps (rtx parallel, rtx src, tree type, int ssize)
+{
+  rtvec vec;
+  int i;
+
+  vec = rtvec_alloc (XVECLEN (parallel, 0));
+  emit_group_load_1 (&RTVEC_ELT (vec, 0), parallel, src, type, ssize);
+
+  /* Convert the vector to look just like the original PARALLEL, except
+     with the computed values.  */
+  for (i = 0; i < XVECLEN (parallel, 0); i++)
+    {
+      rtx e = XVECEXP (parallel, 0, i);
+      rtx d = XEXP (e, 0);
+
+      if (d)
+       {
+         d = force_reg (GET_MODE (d), RTVEC_ELT (vec, i));
+         e = alloc_EXPR_LIST (REG_NOTE_KIND (e), d, XEXP (e, 1));
+       }
+      RTVEC_ELT (vec, i) = e;
+    }
+
+  return gen_rtx_PARALLEL (GET_MODE (parallel), vec);
 }
 
 /* Emit code to move a block SRC to block DST, where SRC and DST are
@@ -1733,6 +1781,27 @@ emit_group_move (rtx dst, rtx src)
                    XEXP (XVECEXP (src, 0, i), 0));
 }
 
+/* Move a group of registers represented by a PARALLEL into pseudos.  */
+
+rtx
+emit_group_move_into_temps (rtx src)
+{
+  rtvec vec = rtvec_alloc (XVECLEN (src, 0));
+  int i;
+
+  for (i = 0; i < XVECLEN (src, 0); i++)
+    {
+      rtx e = XVECEXP (src, 0, i);
+      rtx d = XEXP (e, 0);
+
+      if (d)
+       e = alloc_EXPR_LIST (REG_NOTE_KIND (e), copy_to_reg (d), XEXP (e, 1));
+      RTVEC_ELT (vec, i) = e;
+    }
+
+  return gen_rtx_PARALLEL (GET_MODE (src), vec);
+}
+
 /* Emit code to move a block SRC to a block ORIG_DST of type TYPE,
    where SRC is non-consecutive registers represented by a PARALLEL.
    SSIZE represents the total size of block ORIG_DST, or -1 if not
index 21ff1f4..feac478 100644 (file)
@@ -387,10 +387,16 @@ extern rtx gen_group_rtx (rtx);
    PARALLEL.  */
 extern void emit_group_load (rtx, rtx, tree, int);
 
+/* Similarly, but load into new temporaries.  */
+extern rtx emit_group_load_into_temps (rtx, rtx, tree, int);
+
 /* Move a non-consecutive group of registers represented by a PARALLEL into
    a non-consecutive group of registers represented by a PARALLEL.  */
 extern void emit_group_move (rtx, rtx);
 
+/* Move a group of registers represented by a PARALLEL into pseudos.  */
+extern rtx emit_group_move_into_temps (rtx);
+
 /* Store a BLKmode value from non-consecutive registers represented by a
    PARALLEL.  */
 extern void emit_group_store (rtx, rtx, tree, int);
index 1882901..e4e04d2 100644 (file)
@@ -2536,11 +2536,15 @@ assign_parm_setup_block_p (struct assign_parm_data_one *data)
    present and valid in DATA->STACK_RTL.  */
 
 static void
-assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
+assign_parm_setup_block (struct assign_parm_data_all *all,
+                        tree parm, struct assign_parm_data_one *data)
 {
   rtx entry_parm = data->entry_parm;
   rtx stack_parm = data->stack_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
@@ -2550,6 +2554,8 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
     {
       rtx parmreg = gen_reg_rtx (data->nominal_mode);
 
+      push_to_sequence (all->conversion_insns);
+
       /* For values returned in multiple registers, handle possible
         incompatible calls to emit_group_store.
 
@@ -2572,6 +2578,10 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
       else
        emit_group_store (parmreg, entry_parm, data->nominal_type,
                          int_size_in_bytes (data->nominal_type));
+
+      all->conversion_insns = get_insns ();
+      end_sequence ();
+
       SET_DECL_RTL (parm, parmreg);
       return;
     }
@@ -2609,7 +2619,12 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
 
       /* Handle values in multiple non-contiguous locations.  */
       if (GET_CODE (entry_parm) == PARALLEL)
-       emit_group_store (mem, entry_parm, data->passed_type, size);
+       {
+         push_to_sequence (all->conversion_insns);
+         emit_group_store (mem, entry_parm, data->passed_type, size);
+         all->conversion_insns = get_insns ();
+         end_sequence ();
+       }
 
       else if (size == 0)
        ;
@@ -2648,7 +2663,7 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
            {
              rtx tem, x;
              int by = (UNITS_PER_WORD - size) * BITS_PER_UNIT;
-             rtx reg = gen_rtx_REG (word_mode, REGNO (data->entry_parm));
+             rtx reg = gen_lowpart (word_mode, entry_parm);
 
              x = expand_shift (LSHIFT_EXPR, word_mode, reg,
                                build_int_cst (NULL_TREE, by),
@@ -2657,11 +2672,11 @@ assign_parm_setup_block (tree parm, struct assign_parm_data_one *data)
              emit_move_insn (tem, x);
            }
          else
-           move_block_from_reg (REGNO (data->entry_parm), mem,
+           move_block_from_reg (REGNO (entry_parm), mem,
                                 size_stored / UNITS_PER_WORD);
        }
       else
-       move_block_from_reg (REGNO (data->entry_parm), mem,
+       move_block_from_reg (REGNO (entry_parm), mem,
                             size_stored / UNITS_PER_WORD);
     }
 
@@ -2782,7 +2797,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm,
          emit_move_insn (tempreg, DECL_RTL (parm));
          tempreg = convert_to_mode (GET_MODE (parmreg), tempreg, unsigned_p);
          emit_move_insn (parmreg, tempreg);
-         all->conversion_insns = get_insns();
+         all->conversion_insns = get_insns ();
          end_sequence ();
 
          did_conversion = true;
@@ -3083,7 +3098,7 @@ assign_parms (tree fndecl)
       assign_parm_adjust_stack_rtl (&data);
 
       if (assign_parm_setup_block_p (&data))
-       assign_parm_setup_block (parm, &data);
+       assign_parm_setup_block (&all, parm, &data);
       else if (data.passed_pointer || use_register_for_decl (parm))
        assign_parm_setup_reg (&all, parm, &data);
       else