On Mon, 25 Jun 2018, Richard Biener wrote:
>> Sigh - I see GCC optimizes memmove as well as memcpy in this case, so
>> changing the offending memcpy calls to memmoves would be a bit cleaner. OK to
>> go with this instead?
> 
> I think that's better. Or conditionalizing the offending ones on dest! = src? 

That would work, but would require an extra comparison ('c->n == 3' test would
need to be kept) and also would introduce a poorly-predictable branch depending
on comparator outcomes - something the design of gcc_qsort strives to avoid in
the first place.

This is the patch I'm going to apply.

        PR middle-end/86311
        * sort.cc (REORDER_23): Avoid memcpy with same destination and source.
        (REORDER_45): Likewise.

diff --git a/gcc/sort.cc b/gcc/sort.cc
index a48a477d4e8..293e2058f89 100644
--- a/gcc/sort.cc
+++ b/gcc/sort.cc
@@ -69,7 +69,7 @@ do {                                                     \
   memcpy (&t1, e1 + OFFSET, sizeof (TYPE));              \
   char *out = c->out + OFFSET;                           \
   if (likely (c->n == 3))                                \
-    memcpy (out + 2*STRIDE, e2 + OFFSET, sizeof (TYPE)); \
+    memmove (out + 2*STRIDE, e2 + OFFSET, sizeof (TYPE));\
   memcpy (out, &t0, sizeof (TYPE)); out += STRIDE;       \
   memcpy (out, &t1, sizeof (TYPE));                      \
 } while (0)
@@ -101,7 +101,7 @@ do {                                                     \
   memcpy (&t3, e3 + OFFSET, sizeof (TYPE));              \
   char *out = c->out + OFFSET;                           \
   if (likely (c->n == 5))                                \
-    memcpy (out + 4*STRIDE, e4 + OFFSET, sizeof (TYPE)); \
+    memmove (out + 4*STRIDE, e4 + OFFSET, sizeof (TYPE));\
   memcpy (out, &t0, sizeof (TYPE)); out += STRIDE;       \
   memcpy (out, &t1, sizeof (TYPE)); out += STRIDE;       \
   memcpy (out, &t2, sizeof (TYPE)); out += STRIDE;       \

Reply via email to