This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
complex arg splitting
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: Marcus Meissner <meissner at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org, Richard Henderson <rth at redhat dot com>
- Date: Thu, 19 Feb 2004 09:01:29 +1030
- Subject: complex arg splitting
- References: <OFA3FAB6D2.3586E824-ONC1256E39.0026F7F3-C1256E39.00272145@de.ibm.com> <20040215204632.GA23743@suse.de> <20040215224017.GC26922@bubble.modra.org> <20040218074213.GA4501@suse.de>
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