This is the mail archive of the gcc@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]

rfc: splitting complex arguments


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).


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