User account creation filtered due to spam.

Bug 22237 - [4.0/4.1 Regression] struct copy inlining generates overlapping memcpy
Summary: [4.0/4.1 Regression] struct copy inlining generates overlapping memcpy
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.1.0
: P2 normal
Target Milestone: 4.0.3
Assignee: Richard Henderson
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2005-06-29 23:11 UTC by Joseph S. Myers
Modified: 2005-10-06 22:14 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-10-06 08:49:07


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joseph S. Myers 2005-06-29 23:11:31 UTC
The following test should execute successfully (see C99 6.8.6.4#3 and #4: a
return statement is not an assignment so can be used to copy between overlapping
structures - added in C90 TC1 following DR#001).  With 4.0 branch and mainline,
it aborts when compiled at -O3 (maybe other levels as well) because the
assignment via an inline function call has been wrongly optimized to a direct
assignment.  gcc.c-torture/execute/20010124-1.c used to test for such an issue,
but it now all gets optimized away so a more complicated test such as this one
is needed.

extern void abort (void);
extern void exit (int);
struct s { unsigned char a[256]; };
union u { struct { struct s b; int c; } d; struct { int c; struct s b; } e; };
union u v;
union u v0;
struct s *p = &v.d.b;
struct s *q = &v.e.b;

static inline struct s rp (void) { return *p; }
static inline struct s rq (void) { return *q; }
void pq (void) { *p = rq(); }
void qp (void) { *q = rp(); }

void
init (struct s *sp)
{
  int i;
  for (i = 0; i < 256; i++)
    sp->a[i] = i;
}

void
check (struct s *sp)
{
  int i;
  for (i = 0; i < 256; i++)
    if (sp->a[i] != i)
      abort ();
}

int
main (void)
{
  v = v0;
  init (p);
  qp ();
  check (q);
  v = v0;
  init (q);
  pq ();
  check (p);
  exit (0);
}
Comment 1 Andrew Pinski 2005-06-29 23:16:35 UTC
I cannot reproduce this on powerpc-darwin at all.
Comment 2 joseph@codesourcery.com 2005-06-29 23:22:43 UTC
Subject: Re:  [4.0/4.1 Regression] struct copy
 inlining generates overlapping memcpy

On Wed, 29 Jun 2005, pinskia at gcc dot gnu dot org wrote:

> I cannot reproduce this on powerpc-darwin at all.

Maybe powerpc-darwin has a sympathetic memcpy which acts like memmove.  
(If the output contains a direct memcpy between p and q the problem is 
there even if libc covers it up.)  I get the failure on both 
i686-pc-linux-gnu and x86_64-unknown-linux-gnu with mainline of today.

Comment 3 Andrew Pinski 2005-06-30 02:12:02 UTC
I think this is a latent bug as even 3.4 produces calls to memcpy.

Confirmed, still.
Comment 4 joseph@codesourcery.com 2005-06-30 09:27:40 UTC
Subject: Re:  [4.0/4.1 Regression] struct copy
 inlining generates overlapping memcpy

On Thu, 30 Jun 2005, pinskia at gcc dot gnu dot org wrote:

> I think this is a latent bug as even 3.4 produces calls to memcpy.

Those are memcpy via a stack temporary (each of pq and qp calls memcpy 
twice), which is OK.  The problem is that 4.0/4.1 use a direct memcpy 
between the overlapping structures.  Either indirect copying as with 3.4, 
or using memmove, would be OK, but you can't just convert

t = s1
s2 = t

into

s2 = s1

if s1 and s2 might overlap.

Comment 5 Janis Johnson 2005-09-12 19:51:18 UTC
A regression hunt on mainline for powerpc64-linux (with -m64) shows that the
test starts failing with this patch from rth:

  http://gcc.gnu.org/ml/gcc-cvs/2004-07/msg00914.html

The test does not fail with -m32.
Comment 7 CVS Commits 2005-10-06 22:13:55 UTC
Subject: Bug 22237

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-4_0-branch
Changes by:	rth@gcc.gnu.org	2005-10-06 22:13:49

Modified files:
	gcc            : tree-inline.c 
Added files:
	gcc/testsuite/gcc.c-torture/execute/builtins: pr22237-lib.c 
	                                              pr22237.c 

Log message:
	PR tree-opt/22237
	* tree-inline.c (declare_return_variable): Handle modify_dest not
	being a DECL.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-inline.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.170.8.5&r2=1.170.8.6
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237-lib.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=NONE&r2=1.1.2.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.c-torture/execute/builtins/pr22237.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=NONE&r2=1.1.2.1

Comment 8 Richard Henderson 2005-10-06 22:14:35 UTC
Fixed.