re PR target/18896 (addressing split complex parm)
authorAlan Modra <amodra@bigpond.net.au>
Thu, 23 Dec 2004 00:10:45 +0000 (00:10 +0000)
committerAlan Modra <amodra@gcc.gnu.org>
Thu, 23 Dec 2004 00:10:45 +0000 (10:40 +1030)
PR target/18896
* function.c (split_complex_args): Set DECL_ARTIFICIAL and DECL_IGNORED_P
for real and imaginary parts if the parm is addressable.
(assign_parms_unsplit_complex): If parm addressable, save real
and imaginary parts to a stack temp.  Pass assign_parm_data_all.
(assign_parms): Adjust assign_parms_unsplit_complex call.

From-SVN: r92519

gcc/ChangeLog
gcc/function.c

index 5fe40b5b60ca85cb78419cae398a1ddca99935f6..4c3262596b8f10f2dbeca26ee4b97eee6903ab5e 100644 (file)
@@ -1,3 +1,12 @@
+2004-12-23  Alan Modra  <amodra@bigpond.net.au>
+
+       PR target/18896
+       * function.c (split_complex_args): Set DECL_ARTIFICIAL and DECL_IGNORED_P
+       for real and imaginary parts if the parm is addressable.
+       (assign_parms_unsplit_complex): If parm addressable, save real
+       and imaginary parts to a stack temp.  Pass assign_parm_data_all.
+       (assign_parms): Adjust assign_parms_unsplit_complex call.
+
 2004-12-22  Daniel Berlin  <dberlin@dberlin.org>
        
        * tree.h (DECL_PTA_ALIASVAR): Dead.
index 4f1af4f331d7022392bb4c7626e594ff1d26eb66..1250f36db741a330e2b7496700ca5488c00a25a6 100644 (file)
@@ -2049,6 +2049,7 @@ split_complex_args (tree args)
        {
          tree decl;
          tree subtype = TREE_TYPE (type);
+         bool addressable = TREE_ADDRESSABLE (p);
 
          /* Rewrite the PARM_DECL's type with its component.  */
          TREE_TYPE (p) = subtype;
@@ -2056,11 +2057,20 @@ split_complex_args (tree args)
          DECL_MODE (p) = VOIDmode;
          DECL_SIZE (p) = NULL;
          DECL_SIZE_UNIT (p) = NULL;
+         /* If this arg must go in memory, put it in a pseudo here.
+            We can't allow it to go in memory as per normal parms,
+            because the usual place might not have the imag part
+            adjacent to the real part.  */
+         DECL_ARTIFICIAL (p) = addressable;
+         DECL_IGNORED_P (p) = addressable;
+         TREE_ADDRESSABLE (p) = 0;
          layout_decl (p, 0);
 
          /* Build a second synthetic decl.  */
          decl = build_decl (PARM_DECL, NULL_TREE, subtype);
          DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (p);
+         DECL_ARTIFICIAL (decl) = addressable;
+         DECL_IGNORED_P (decl) = addressable;
          layout_decl (decl, 0);
 
          /* Splice it in; skip the new decl.  */
@@ -2924,9 +2934,10 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm,
    undo the frobbing that we did in assign_parms_augmented_arg_list.  */
 
 static void
-assign_parms_unsplit_complex (tree orig_fnargs, tree fnargs)
+assign_parms_unsplit_complex (struct assign_parm_data_all *all, tree fnargs)
 {
   tree parm;
+  tree orig_fnargs = all->orig_fnargs;
 
   for (parm = orig_fnargs; parm; parm = TREE_CHAIN (parm))
     {
@@ -2943,7 +2954,26 @@ assign_parms_unsplit_complex (tree orig_fnargs, tree fnargs)
              real = gen_lowpart_SUBREG (inner, real);
              imag = gen_lowpart_SUBREG (inner, imag);
            }
-         tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
+
+         if (TREE_ADDRESSABLE (parm))
+           {
+             rtx rmem, imem;
+             HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (parm));
+
+             /* split_complex_arg put the real and imag parts in
+                pseudos.  Move them to memory.  */
+             tmp = assign_stack_local (DECL_MODE (parm), size, 0);
+             set_mem_attributes (tmp, parm, 1);
+             rmem = adjust_address_nv (tmp, inner, 0);
+             imem = adjust_address_nv (tmp, inner, GET_MODE_SIZE (inner));
+             push_to_sequence (all->conversion_insns);
+             emit_move_insn (rmem, real);
+             emit_move_insn (imem, imag);
+             all->conversion_insns = get_insns ();
+             end_sequence ();
+           }
+         else
+           tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
          SET_DECL_RTL (parm, tmp);
 
          real = DECL_INCOMING_RTL (fnargs);
@@ -3055,7 +3085,7 @@ assign_parms (tree fndecl)
     }
 
   if (targetm.calls.split_complex_arg && fnargs != all.orig_fnargs)
-    assign_parms_unsplit_complex (all.orig_fnargs, fnargs);
+    assign_parms_unsplit_complex (&all, fnargs);
 
   /* Output all parameter conversion instructions (possibly including calls)
      now that all parameters have been copied out of hard registers.  */