diff --git a/ChangeLog.tile b/ChangeLog.tile index 5cdc293f8e..83136aa6c3 100644 --- a/ChangeLog.tile +++ b/ChangeLog.tile @@ -1,3 +1,8 @@ +2012-05-12 Chris Metcalf + + * sysdeps/tile/tilegx/memcpy.c: Allow memcpy(p, p, n) + without corrupting memory at "p". + 2012-05-12 Chris Metcalf * sysdeps/tile/__tls_get_addr.S: Use __WORDSIZE, not _LP64. diff --git a/sysdeps/tile/tilegx/memcpy.c b/sysdeps/tile/tilegx/memcpy.c index 9cfb283c82..dd6e30dd60 100644 --- a/sysdeps/tile/tilegx/memcpy.c +++ b/sysdeps/tile/tilegx/memcpy.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2011 Free Software Foundation, Inc. +/* Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Chris Metcalf , 2011. @@ -107,6 +107,17 @@ __memcpy (void *__restrict dstv, const void *__restrict srcv, size_t n) n -= sizeof (word_t)) *dst8++ = *src8++; + /* If copying to self, return. The test is cheap enough + that we do it despite the fact that the memcpy() contract + doesn't require us to support overlapping dst and src. + This is the most common case of overlap, and any close + overlap will cause corruption due to the wh64 below. + This case is particularly important since the compiler + will emit memcpy() calls for aggregate copies even if it + can't prove that src != dst. */ + if (__builtin_expect (dst8 == src8, 0)) + return dstv; + for (; n >= CHIP_L2_LINE_SIZE ();) { __insn_wh64 (dst8);