This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: patch: split complex arguments (heads up)


I still need to fix function return values to go in a pair of FPRs. Tomorrow when I'm more awake.

Same patch as before, with back end tweaks for FUNCTION_VALUE and LIBCALL_VALUE.


Bootstrapped and regtested on ppc-linux by changing the SPLIT_COMPLEX_ARGS macro to 1.

OK?

2003-05-31 Aldy Hernandez <aldyh@redhat.com>

* function.c (assign_parms): Split complex arguments.

* doc/tm.texi (SPLIT_COMPLEX_ARGS): Document.

	* expr.h (SPLIT_COMPLEX_ARGS): Define.
	(split_complex_types): Protoize.
	(split_complex_values): Protoize.

	* calls.c (expand_call): Split complex arguments on architectures
	that require it.
	(split_complex_values): New.
	(split_complex_types): New.

	* config/rs6000/rs6000.c (rs6000_libcall_value): New.
	(rs6000_function_value): Handle complex values on AIX.
	(rs6000_complex_function_value): New.
	
	* config/rs6000/rs6000-protos.h (rs6000_libcall_value): Protoize.

	* config/rs6000/rs6000.h (LIBCALL_VALUE): Call function.
	(SPLIT_COMPLEX_ARGS): New.

Index: function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.427
diff -c -p -r1.427 function.c
*** function.c 11 May 2003 19:21:31 -0000 1.427
--- function.c 31 May 2003 16:43:58 -0000
*************** static void prepare_function_start PARAM
*** 296,301 ****
--- 296,302 ----
static void do_clobber_return_reg PARAMS ((rtx, void *));
static void do_use_return_reg PARAMS ((rtx, void *));
static void instantiate_virtual_regs_lossage PARAMS ((rtx));
+ static tree split_complex_args (tree);

/* Pointer to chain of `struct function' for containing functions. */
static GTY(()) struct function *outer_function_chain;
*************** assign_parms (fndecl)
*** 4346,4352 ****
given as a constant and a tree-expression. */
struct args_size stack_args_size;
tree fntype = TREE_TYPE (fndecl);
! tree fnargs = DECL_ARGUMENTS (fndecl);
/* This is used for the arg pointer when referring to stack args. */
rtx internal_arg_pointer;
/* This is a dummy PARM_DECL that we used for the function result if
--- 4347,4353 ----
given as a constant and a tree-expression. */
struct args_size stack_args_size;
tree fntype = TREE_TYPE (fndecl);
! tree fnargs = DECL_ARGUMENTS (fndecl), orig_fnargs;
/* This is used for the arg pointer when referring to stack args. */
rtx internal_arg_pointer;
/* This is a dummy PARM_DECL that we used for the function result if
*************** assign_parms (fndecl)
*** 4400,4408 ****
--- 4401,4414 ----
fnargs = function_result_decl;
}


+ orig_fnargs = fnargs;
+
max_parm_reg = LAST_VIRTUAL_REGISTER + 1;
parm_reg_stack_loc = (rtx *) ggc_alloc_cleared (max_parm_reg * sizeof (rtx));


+   if (SPLIT_COMPLEX_ARGS)
+     fnargs = split_complex_args (fnargs);
+
  #ifdef REG_PARM_STACK_SPACE
  #ifdef MAYBE_REG_PARM_STACK_SPACE
    reg_parm_stack_space = MAYBE_REG_PARM_STACK_SPACE;
*************** assign_parms (fndecl)
*** 5187,5192 ****
--- 5193,5227 ----
  	}
      }

+ if (SPLIT_COMPLEX_ARGS)
+ {
+ parm = orig_fnargs;
+
+ for (; parm; parm = TREE_CHAIN (parm))
+ {
+ tree type = TREE_TYPE (parm);
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ SET_DECL_RTL (parm,
+ gen_rtx_CONCAT (DECL_MODE (parm),
+ DECL_RTL (fnargs),
+ DECL_RTL (TREE_CHAIN (fnargs))));
+ DECL_INCOMING_RTL (parm)
+ = gen_rtx_CONCAT (DECL_MODE (parm),
+ DECL_INCOMING_RTL (fnargs),
+ DECL_INCOMING_RTL (TREE_CHAIN (fnargs)));
+ fnargs = TREE_CHAIN (fnargs);
+ }
+ else
+ {
+ SET_DECL_RTL (parm, DECL_RTL (fnargs));
+ DECL_INCOMING_RTL (parm) = DECL_INCOMING_RTL (fnargs);
+ }
+ fnargs = TREE_CHAIN (fnargs);
+ }
+ }
+
/* Output all parameter conversion instructions (possibly including calls)
now that all parameters have been copied out of hard registers. */
emit_insn (conversion_insns);
*************** assign_parms (fndecl)
*** 5289,5294 ****
--- 5324,5359 ----
current_function_return_rtx = real_decl_rtl;
}
}
+ }
+
+ static tree
+ split_complex_args (tree args)
+ {
+ tree p;
+
+ args = copy_list (args);
+
+ for (p = args; p; p = TREE_CHAIN (p))
+ {
+ tree complex_type = TREE_TYPE (p);
+
+ if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ {
+ tree decl;
+ tree subtype = TREE_TYPE (complex_type);
+
+ /* Rewrite the PARM_DECL's type with its component. */
+ TREE_TYPE (p) = subtype;
+ DECL_ARG_TYPE (p) = TREE_TYPE (DECL_ARG_TYPE (p));
+
+ decl = build_decl (PARM_DECL, NULL_TREE, subtype);
+ DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (p);
+ TREE_CHAIN (decl) = TREE_CHAIN (p);
+ TREE_CHAIN (p) = decl;
+ }
+ }
+
+ return args;
}

/* Indicate whether REGNO is an incoming argument to the current function
Index: expr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.h,v
retrieving revision 1.137
diff -c -p -r1.137 expr.h
*** expr.h 12 May 2003 09:51:11 -0000 1.137
--- expr.h 31 May 2003 16:43:58 -0000
*************** do { \
*** 158,163 ****
--- 158,171 ----
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) PARM_BOUNDARY
#endif


+ /* Define to nonzero if complex arguments should be split into their
+    corresponding components.  */
+ #ifndef SPLIT_COMPLEX_ARGS
+ #define SPLIT_COMPLEX_ARGS 0
+ #endif
+ tree split_complex_types (tree);
+ tree split_complex_values (tree);
+
  /* Provide a default value for STRICT_ARGUMENT_NAMING.  */
  #ifndef STRICT_ARGUMENT_NAMING
  #define STRICT_ARGUMENT_NAMING 0
Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.273
diff -c -p -r1.273 calls.c
*** calls.c	3 May 2003 14:25:20 -0000	1.273
--- calls.c	31 May 2003 16:44:02 -0000
*************** expand_call (exp, target, ignore)
*** 2072,2077 ****
--- 2072,2078 ----
    rtx tail_call_insns = NULL_RTX;
    /* Data type of the function.  */
    tree funtype;
+   tree type_arg_types;
    /* Declaration of the function being called,
       or 0 if the function is computed (not known by name).  */
    tree fndecl = 0;
*************** expand_call (exp, target, ignore)
*** 2307,2312 ****
--- 2308,2323 ----
      abort ();
    funtype = TREE_TYPE (funtype);

+ /* Munge the tree to split complex arguments into their imaginary
+ and real parts. */
+ if (SPLIT_COMPLEX_ARGS)
+ {
+ type_arg_types = split_complex_types (TYPE_ARG_TYPES (funtype));
+ actparms = split_complex_values (actparms);
+ }
+ else
+ type_arg_types = TYPE_ARG_TYPES (funtype);
+
/* See if this is a call to a function that can return more than once
or a call to longjmp or malloc. */
flags |= special_function_p (fndecl, flags);
*************** expand_call (exp, target, ignore)
*** 2360,2368 ****


    if ((STRICT_ARGUMENT_NAMING
         || ! PRETEND_OUTGOING_VARARGS_NAMED)
!       && TYPE_ARG_TYPES (funtype) != 0)
      n_named_args
!       = (list_length (TYPE_ARG_TYPES (funtype))
  	 /* Don't include the last named arg.  */
  	 - (STRICT_ARGUMENT_NAMING ? 0 : 1)
  	 /* Count the struct value address, if it is passed as a parm.  */
--- 2371,2379 ----

    if ((STRICT_ARGUMENT_NAMING
         || ! PRETEND_OUTGOING_VARARGS_NAMED)
!       && type_arg_types != 0)
      n_named_args
!       = (list_length (type_arg_types)
  	 /* Don't include the last named arg.  */
  	 - (STRICT_ARGUMENT_NAMING ? 0 : 1)
  	 /* Count the struct value address, if it is passed as a parm.  */
*************** expand_call (exp, target, ignore)
*** 3442,3447 ****
--- 3453,3534 ----
      }

    return target;
+ }
+
+ /* Traverse an argument list in VALUES and expand all complex
+    arguments into their components.  */
+ tree
+ split_complex_values (tree values)
+ {
+   tree p;
+
+   values = copy_list (values);
+
+   for (p = values; p; p = TREE_CHAIN (p))
+     {
+       tree complex_value = TREE_VALUE (p);
+       tree complex_type;
+
+       complex_type = TREE_TYPE (complex_value);
+       if (!complex_type)
+ 	continue;
+
+       if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ 	{
+ 	  tree subtype;
+ 	  tree real, imag, next;
+
+ 	  subtype = TREE_TYPE (complex_type);
+ 	  complex_value = save_expr (complex_value);
+ 	  real = build1 (REALPART_EXPR, subtype, complex_value);
+ 	  imag = build1 (IMAGPART_EXPR, subtype, complex_value);
+
+ 	  TREE_VALUE (p) = real;
+ 	  next = TREE_CHAIN (p);
+ 	  imag = build_tree_list (NULL_TREE, imag);
+ 	  TREE_CHAIN (p) = imag;
+ 	  TREE_CHAIN (imag) = next;
+
+ 	  /* Skip the newly created node.  */
+ 	  p = TREE_CHAIN (p);
+ 	}
+     }
+
+   return values;
+ }
+
+ /* Traverse a list of TYPES and expand all complex types into their
+    components.  */
+ tree
+ split_complex_types (tree types)
+ {
+   tree p;
+
+   types = copy_list (types);
+
+   for (p = types; p; p = TREE_CHAIN (p))
+     {
+       tree complex_type = TREE_VALUE (p);
+
+       if (TREE_CODE (complex_type) == COMPLEX_TYPE)
+ 	{
+ 	  tree next, imag;
+
+ 	  /* Rewrite complex type with component type.  */
+ 	  TREE_VALUE (p) = TREE_TYPE (complex_type);
+ 	  next = TREE_CHAIN (p);
+
+ 	  /* Add another component type for the imaginary part.  */
+ 	  imag = build_tree_list (NULL_TREE, TREE_VALUE (p));
+ 	  TREE_CHAIN (p) = imag;
+ 	  TREE_CHAIN (imag) = next;
+
+ 	  /* Skip the newly created node.  */
+ 	  p = TREE_CHAIN (p);
+ 	}
+     }
+
+   return types;
  }
  
  /* Output a library call to function FUN (a SYMBOL_REF rtx).
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.222
diff -c -p -r1.222 tm.texi
*** doc/tm.texi	19 May 2003 20:03:42 -0000	1.222
--- doc/tm.texi	31 May 2003 16:44:10 -0000
*************** the structure-value address.  On many ma
*** 3797,3802 ****
--- 3797,3813 ----
  used for this purpose since all function arguments are pushed on the
  stack.

+ @findex SPLIT_COMPLEX_ARGS
+ @item SPLIT_COMPLEX_ARGS
+
+ Define this macro to a nonzero value if complex function arguments
+ should be split into their corresponding components. By default, GCC
+ will attempt to pack complex arguments into the target's word size.
+ Some ABIs require complex arguments to be split and treated as their
+ individual components. For example, on AIX64, complex floats should
+ be passed in a pair of floating point registers, even though a complex
+ float would fit in one 64-bit floating point register.
+
@findex LOAD_ARGS_REVERSED
@item LOAD_ARGS_REVERSED
If defined, the order in which arguments are loaded into their
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.481
diff -c -p -r1.481 rs6000.c
*** config/rs6000/rs6000.c 19 May 2003 21:33:57 -0000 1.481
--- config/rs6000/rs6000.c 31 May 2003 16:44:18 -0000
*************** static rtx rs6000_got_sym PARAMS ((void)
*** 312,317 ****
--- 312,318 ----
static inline int rs6000_tls_symbol_ref_1 PARAMS ((rtx *, void *));
static const char *rs6000_get_some_local_dynamic_name PARAMS ((void));
static int rs6000_get_some_local_dynamic_name_1 PARAMS ((rtx *, void *));
+ static rtx rs6000_complex_function_value (enum machine_mode);


/* Hash table stuff for keeping track of TOC entries. */

*************** rs6000_memory_move_cost (mode, class, in
*** 14361,14366 ****
--- 14362,14394 ----
      return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
  }

+ /* Return an RTX representing where to find the function value of a
+ function returning MODE. */
+ static rtx
+ rs6000_complex_function_value (enum machine_mode mode)
+ {
+ unsigned int regno;
+ rtx r1, r2;
+ enum machine_mode inner = GET_MODE_INNER (mode);
+
+ if (FLOAT_MODE_P (mode))
+ regno = FP_ARG_RETURN;
+ else
+ {
+ regno = GP_ARG_RETURN;
+
+ /* 32-bit is OK since it'll go in r3/r4. */
+ if (TARGET_32BIT)
+ return gen_rtx_REG (mode, regno);
+ }
+
+ r1 = gen_rtx_EXPR_LIST (inner, gen_rtx_REG (inner, regno),
+ const0_rtx);
+ r2 = gen_rtx_EXPR_LIST (inner, gen_rtx_REG (inner, regno + 1),
+ GEN_INT (GET_MODE_UNIT_SIZE (inner)));
+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r2));
+ }
+
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
If the precise function being called is known, FUNC is its FUNCTION_DECL;
*************** rs6000_function_value (tree valtype, tre
*** 14386,14393 ****
--- 14414,14445 ----


if (TREE_CODE (valtype) == REAL_TYPE && TARGET_HARD_FLOAT && TARGET_FPRS)
regno = FP_ARG_RETURN;
+ else if (TREE_CODE (valtype) == COMPLEX_TYPE
+ && TARGET_HARD_FLOAT
+ && SPLIT_COMPLEX_ARGS)
+ return rs6000_complex_function_value (mode);
else if (TREE_CODE (valtype) == VECTOR_TYPE && TARGET_ALTIVEC)
regno = ALTIVEC_ARG_RETURN;
+ else
+ regno = GP_ARG_RETURN;
+
+ return gen_rtx_REG (mode, regno);
+ }
+
+ /* Define how to find the value returned by a library function
+ assuming the value has mode MODE. */
+ rtx
+ rs6000_libcall_value (enum machine_mode mode)
+ {
+ unsigned int regno;
+
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ && TARGET_HARD_FLOAT && TARGET_FPRS)
+ regno = FP_ARG_RETURN;
+ else if (ALTIVEC_VECTOR_MODE (mode))
+ regno = ALTIVEC_ARG_RETURN;
+ else if (COMPLEX_MODE_P (mode) && SPLIT_COMPLEX_ARGS)
+ return rs6000_complex_function_value (mode);
else
regno = GP_ARG_RETURN;


Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.54
diff -c -p -r1.54 rs6000-protos.h
*** config/rs6000/rs6000-protos.h	15 May 2003 20:01:09 -0000	1.54
--- config/rs6000/rs6000-protos.h	31 May 2003 16:44:18 -0000
*************** extern void setup_incoming_varargs PARAM
*** 153,158 ****
--- 153,159 ----
  					    enum machine_mode, tree,
  					    int *, int));
  extern rtx rs6000_function_value (tree, tree);
+ extern rtx rs6000_libcall_value (enum machine_mode);
  extern struct rtx_def *rs6000_va_arg PARAMS ((tree, tree));
  extern int function_ok_for_sibcall PARAMS ((tree));
  #ifdef ARGS_SIZE_RTX
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.275
diff -c -p -r1.275 rs6000.h
*** config/rs6000/rs6000.h	19 May 2003 17:39:50 -0000	1.275
--- config/rs6000/rs6000.h	31 May 2003 16:44:20 -0000
*************** typedef struct rs6000_stack {
*** 1583,1593 ****
  /* Define how to find the value returned by a library function
     assuming the value has mode MODE.  */

! #define LIBCALL_VALUE(MODE)						\
!   gen_rtx_REG (MODE, ALTIVEC_VECTOR_MODE (MODE) ? ALTIVEC_ARG_RETURN	\
! 		     : GET_MODE_CLASS (MODE) == MODE_FLOAT		\
! 		     && TARGET_HARD_FLOAT && TARGET_FPRS		\
! 		     ? FP_ARG_RETURN : GP_ARG_RETURN)

  /* The AIX ABI for the RS/6000 specifies that all structures are
     returned in memory.  The Darwin ABI does the same.  The SVR4 ABI
--- 1583,1589 ----
  /* Define how to find the value returned by a library function
     assuming the value has mode MODE.  */

! #define LIBCALL_VALUE(MODE) rs6000_libcall_value ((MODE))

  /* The AIX ABI for the RS/6000 specifies that all structures are
     returned in memory.  The Darwin ABI does the same.  The SVR4 ABI
*************** typedef struct rs6000_args
*** 1814,1819 ****
--- 1810,1822 ----

  #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
    function_arg_boundary (MODE, TYPE)
+
+ /* Define to nonzero if complex arguments should be split into their
+    corresponding components.
+
+    This should be set for Linux and Darwin as well, but we can't break
+    the ABIs at the moment.  For now, only AIX gets fixed.  */
+ #define SPLIT_COMPLEX_ARGS (DEFAULT_ABI == ABI_AIX)

/* Perform any needed actions needed for a function that is receiving a
variable number of arguments.



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]