diff mbox series

[alpha] : Correctly handle split _Complex float variable arguments

Message ID CAFULd4aMoN1vTK=Gt=X3gdk1MiExA8dobKwUVesMeo8KmsyrPQ@mail.gmail.com
State New
Headers show
Series [alpha] : Correctly handle split _Complex float variable arguments | expand

Commit Message

Uros Bizjak Jan. 16, 2019, 3:55 p.m. UTC
Hello!

Attached patch corrects handing of split _Complex float variable
arguments. Alpha is not able to pass 32bit floats in float registers
as variable arguments (see the comment in alpha_pass_by_reference), so
we pass them by reference. However, complex float arguments are split
to their real and imaginary part and passed separately. When passed by
reference, every part is passed separately by a separate reference.
Attached patch fixes this oversight in alpha_gimplify_va_arg.

The patch fixes:

FAIL: gcc.dg/compat/scalar-by-value-4 c_compat_x_tst.o-c_compat_y_tst.o execute
FAIL: gcc.dg/compat/scalar-return-4 c_compat_x_tst.o-c_compat_y_tst.o execute

2019-01-16  Uroš Bizjak  <ubizjak@gmail.com>

    * config/alpha/alpha.c (alpha_gimplify_va_arg):
    Handle split indirect COMPLEX_TYPE arguments.

Bootstrapped and regression tested on alphaev68-linux-gnu.

Committed to mainline SVN.

Uros.
diff mbox series

Patch

diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index ce45c54eeb7a..f0e8124797f3 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -6378,8 +6378,40 @@  alpha_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
   offset = get_initialized_tmp_var (t, pre_p, NULL);
 
   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
+
   if (indirect)
-    type = build_pointer_type_for_mode (type, ptr_mode, true);
+    {
+      if (TREE_CODE (type) == COMPLEX_TYPE
+	  && targetm.calls.split_complex_arg (type))
+	{
+	  tree real_part, imag_part, real_temp;
+
+	  tree ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
+						       ptr_mode, true);
+
+	  real_part = alpha_gimplify_va_arg_1 (ptr_type, base,
+					       offset, pre_p);
+	  real_part = build_va_arg_indirect_ref (real_part);
+
+	  /* Copy the value into a new temporary, lest the formal temporary
+	     be reused out from under us.  */
+	  real_temp = get_initialized_tmp_var (real_part, pre_p, NULL);
+
+	  imag_part = alpha_gimplify_va_arg_1 (ptr_type, base,
+					       offset, pre_p);
+	  imag_part = build_va_arg_indirect_ref (imag_part);
+
+	  r = build2 (COMPLEX_EXPR, type, real_temp, imag_part);
+
+	  /* Stuff the offset temporary back into its field.  */
+	  gimplify_assign (unshare_expr (offset_field),
+			   fold_convert (TREE_TYPE (offset_field), offset),
+			   pre_p);
+	  return r;
+	}
+      else
+	type = build_pointer_type_for_mode (type, ptr_mode, true);
+    }
 
   /* Find the value.  Note that this will be a stable indirection, or
      a composite of stable indirections in the case of complex.  */