Bug 18896 - addressing split complex parm
Summary: addressing split complex parm
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.0
Assignee: Alan Modra
URL:
Keywords: ABI, ice-on-valid-code, patch, wrong-code
Depends on:
Blocks:
 
Reported: 2004-12-09 01:45 UTC by Alan Modra
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Host:
Target: powerpc64-linux
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
testcase (109 bytes, text/plain)
2004-12-09 01:48 UTC, Alan Modra
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Modra 2004-12-09 01:45:38 UTC
On powerpc64-linux, with this testcase

int f (_Complex double a)
{
  extern _Complex double cd;
  return memcmp (&a, &cd, sizeof (a));
}

I'm hitting this assert in expand_expr_addr_expr_1

	  /* If the DECL isn't in memory, then the DECL wasn't properly
	     marked TREE_ADDRESSABLE, which will be either a front-end
	     or a tree optimizer bug.  */
	  gcc_assert (GET_CODE (result) == MEM);

The decl rtl is:

(concat:DC (mem/i:DF (reg/f:DI 113 virtual-incoming-args) [0 a+0 S8 A64])
    (reg/v:DF 119 [ a+8 ]))

That's buggy.  We shouldn't have part of the concat in memory, and part
in a reg.  Fixed with:

	* function.c (split_complex_args): Copy TREE_ADDRESSABLE for
	synthetic decl.

With that, we get 

(concat:DC (mem/i:DF (reg/f:DI 113 virtual-incoming-args) [0 a+0 S8 A64])
    (mem/i:DF (plus:DI (reg/f:DI 113 virtual-incoming-args)
            (const_int 8 [0x8])) [0 D.1119+0 S8 A64]))

Now I'm not sure where this should be fixed.  I'm guessing that the hack
I have in my local tree in expand_expr_addr_expr_1 to look inside the
CONCAT isn't the right place to fix this.  Also there's a much worse
problem;  The two pieces of the concat might not be adjacent.  Consider

int g (_Complex float a)
{
  extern _Complex float cf;
  return memcmp (&a, &cf, sizeof (a));
}

For this, the decl rtl is now

(concat:SC (mem/i:SF (reg/f:DI 113 virtual-incoming-args) [0 a+0 S4 A64])
    (mem/i:SF (plus:DI (reg/f:DI 113 virtual-incoming-args)
            (const_int 8 [0x8])) [0 D.1128+0 S4 A64]))

Notice that the two mems are 8 bytes apart but a _Complex float in
memory should have the two 4 byte parts adjacent.


Index: gcc/function.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/function.c,v
retrieving revision 1.592
diff -u -p -r1.592 function.c
--- gcc/function.c	1 Dec 2004 18:13:30 -0000	1.592
+++ gcc/function.c	9 Dec 2004 00:48:12 -0000
@@ -2061,6 +2061,7 @@ split_complex_args (tree args)
 	  /* Build a second synthetic decl.  */
 	  decl = build_decl (PARM_DECL, NULL_TREE, subtype);
 	  DECL_ARG_TYPE (decl) = DECL_ARG_TYPE (p);
+	  TREE_ADDRESSABLE (decl) = TREE_ADDRESSABLE (p);
 	  layout_decl (decl, 0);
 
 	  /* Splice it in; skip the new decl.  */
Comment 1 Alan Modra 2004-12-09 01:48:20 UTC
Created attachment 7709 [details]
testcase
Comment 2 Alan Modra 2004-12-09 05:51:37 UTC
Fixing assign_parms_unsplit_complex
Comment 3 Richard Henderson 2004-12-09 06:58:07 UTC
I think the correct solution is to explicitly *clear* TREE_ADDRESSABLE in
split_complex_args and set DECL_ARTIFICIAL so that the two pieces get 
allocated to pseudo registers.  Then unsplit_complex needs to notice that
the original decl is TREE_ADDRESSABLE, allocate contiguous memory, and store
the two pseudos into it.

Something to work on for 4.1 might be noticing that the two members of the
concat live in adjacent parameter memory, and promote that parameter memory
to the address of the entire complex.  That wouldn't be particularly easy 
at the stage that unsplit_complex is currently called.
Comment 5 GCC Commits 2004-12-23 00:11:15 UTC
Subject: Bug 18896

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	amodra@gcc.gnu.org	2004-12-23 00:10:50

Modified files:
	gcc            : ChangeLog function.c 

Log message:
	PR target/18896
	* function.c (split_complex_args): Set DECL_ARTIFICIAL and DECL_IGNORED_P
	for real and imaginary parts if the parm is addressable.
	(assign_parms_unsplit_complex): If parm addressable, save real
	and imaginary parts to a stack temp.  Pass assign_parm_data_all.
	(assign_parms): Adjust assign_parms_unsplit_complex call.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6924&r2=2.6925
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/function.c.diff?cvsroot=gcc&r1=1.595&r2=1.596

Comment 6 Alan Modra 2004-12-23 00:33:45 UTC
Fixed mainline.  gcc-3.4 not affected by this particular problem.