rfc: splitting complex arguments

Aldy Hernandez aldyh@redhat.com
Fri May 23 15:18:00 GMT 2003


The background is this:

        In the AIX-64 abi, complex floats (SCmode) must be promoted to
        two 64-bit quantities and passed in f1/f2.  Currently, GCC
        incorrectly packs the real and imaginary parts of an SCmode
        into a single 64-bit FPR.

...and the thread started here:

	http://gcc.gnu.org/ml/gcc-patches/2003-01/msg01502.html

I'm tackling this ABI problem again.  Last time around there were no 
suggestions on how to approach this problem, aside from Kenner's 
comment that PROMOTE_MODE was *not* the right way.

I talked it over with rth, and he's suggested splitting the complex 
arguments in the middle end, particularly expand_call() and 
assign_parms().  I have preliminary patch doing this-- the expand_call 
bits.  It works by munging the tree at the right place and letting 
expand_call do it's thing.

Does anyone object to this approach, or have any comments?  I'd hate to 
continue down this path, and have someone object to it at the last 
minute.

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

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

	* config/rs6000/rs6000.h (SPLIT_COMPLEX_ARGS): New.

	* expr.h (SPLIT_COMPLEX_ARGS): Define.

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

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	23 May 2003 15:07:11 -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.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.274
diff -c -p -r1.274 rs6000.h
*** config/rs6000/rs6000.h	15 May 2003 20:01:10 -0000	1.274
--- config/rs6000/rs6000.h	23 May 2003 15:07:12 -0000
*************** typedef struct rs6000_args
*** 1794,1799 ****
--- 1794,1803 ----
   #define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
     function_arg_boundary (MODE, TYPE)

+ /* Define to nonzero if complex arguments should be split into their
+    corresponding components.  */
+ #define SPLIT_COMPLEX_ARGS (TARGET_64BIT && DEFAULT_ABI == ABI_AIX)
+
   /* Perform any needed actions needed for a function that is receiving 
a
      variable number of arguments.

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	23 May 2003 15:07:12 -0000
*************** do {							\
*** 158,163 ****
--- 158,169 ----
   #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
+
   /* 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	23 May 2003 15:07:13 -0000
*************** static tree fix_unsafe_tree		PARAMS ((tr
*** 193,198 ****
--- 193,200 ----
   #ifdef REG_PARM_STACK_SPACE
   static rtx save_fixed_argument_area	PARAMS ((int, rtx, int *, int *));
   static void restore_fixed_argument_area	PARAMS ((rtx, rtx, int, int));
+ static tree split_complex_types (tree);
+ static tree split_complex_values (tree);
   #endif
   
   /* If WHICH is 1, return 1 if EXP contains a call to the built-in 
function
*************** expand_call (exp, target, ignore)
*** 2307,2312 ****
--- 2309,2327 ----
       abort ();
     funtype = TREE_TYPE (funtype);

+   /* Munge the tree to split complex arguments into their imaginary
+      and real parts.  */
+   if (SPLIT_COMPLEX_ARGS)
+     {
+       tree arg_types, arg_values;
+
+       arg_types = split_complex_types (TYPE_ARG_TYPES (funtype));
+       arg_values = split_complex_values (actparms);
+
+       TYPE_ARG_TYPES (funtype) = arg_types;
+       actparms = arg_values;
+     }
+
     /* 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)
*** 3442,3447 ****
--- 3457,3538 ----
       }

     return target;
+ }
+
+ /* Traverse an argument list in VALUES and expand all complex
+    arguments into their components.  */
+ static tree
+ split_complex_values (tree values)
+ {
+   tree p;
+
+   /*endian*/
+   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);
+ 	  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.  */
+ static 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).



More information about the Gcc mailing list