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; \