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]

complex arg splitting


extern void u (int, int);

void f(__complex__ int x)
{
  u (0, x);
}

powerpc64-linux-gcc -m64 -O -S /src/tmp/floatice.c
/src/tmp/floatice.c:6: internal compiler error: in subreg_hard_regno, at
emit-rtl.c:1114 (955 on mainline)

This should fix it.  The complex arg splitting code gives
f(__complex__ int x) a decl_rtl of (concat:CSI (reg/v:DI 118 [ x ])
(reg/v:DI 119 [ x+8 ])) on ppc64, which has a mode mismatch.  The outer
CSImode concat needs components of SImode.  As it was, taking the real
part of x resulted in the high 32 bits of reg 118.

	* function.c (assign_parms): When building decl_rtl for
	SPLIT_COMPLEX_ARGS, ensure inner modes of concat match outer.

Index: gcc/function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.387.2.22
diff -u -p -r1.387.2.22 function.c
--- gcc/function.c	11 Feb 2004 07:38:52 -0000	1.387.2.22
+++ gcc/function.c	18 Feb 2004 22:04:48 -0000
@@ -5229,15 +5229,27 @@ assign_parms (fndecl)
 	{
 	  if (TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE)
 	    {
-	      rtx tmp;
+	      rtx tmp, real, imag;
+	      enum machine_mode inner = GET_MODE_INNER (DECL_MODE (parm));
 
-	      SET_DECL_RTL (parm,
-			    gen_rtx_CONCAT (DECL_MODE (parm),
-					    DECL_RTL (fnargs),
-					    DECL_RTL (TREE_CHAIN (fnargs))));
-	      tmp = gen_rtx_CONCAT (DECL_MODE (parm),
-				    DECL_INCOMING_RTL (fnargs),
-				    DECL_INCOMING_RTL (TREE_CHAIN (fnargs)));
+	      real = DECL_RTL (fnargs);
+	      imag = DECL_RTL (TREE_CHAIN (fnargs));
+	      if (inner != GET_MODE (real))
+		{
+		  real = gen_lowpart_SUBREG (inner, real);
+		  imag = gen_lowpart_SUBREG (inner, imag);
+		}
+	      tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
+	      SET_DECL_RTL (parm, tmp);
+
+	      real = DECL_INCOMING_RTL (fnargs);
+	      imag = DECL_INCOMING_RTL (TREE_CHAIN (fnargs));
+	      if (inner != GET_MODE (real))
+		{
+		  real = gen_lowpart_SUBREG (inner, real);
+		  imag = gen_lowpart_SUBREG (inner, imag);
+		}
+	      tmp = gen_rtx_CONCAT (DECL_MODE (parm), real, imag);
 	      set_decl_incoming_rtl (parm, tmp);
 	      fnargs = TREE_CHAIN (fnargs);
 	    }

I'd also like to add the following testcase to gcc.c-torture/compile/

extern void u (int, int);
extern void v (float, float);

void f(__complex__ int x)
{
  u (0, x);
}

void g(__complex__ float x)
{
  v (0, x);
}

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


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