On Tue, Aug 28, 2018 at 11:14 AM Alexander Monakov <amona...@ispras.ru> wrote:
>
> This adds a stable sort to sort.cc: mergesort implementation is stable, so
> we just need network sort limited to sizes 2-3 to get the complete sort 
> stable.
>
> As I don't want to duplicate code for this, I've chosen to have gcc_qsort
> accept bit-inverted 'size' parameter to request stable sorting.

OK.

>         * gcc/sort.cc (struct sort_ctx): New field 'nlim'. Use it...
>         (mergesort): ... here as maximum count for using netsort.
>         (gcc_qsort): Set nlim to 3 if stable sort is requested.
>         (gcc_stablesort): New.
>         * gcc/system.h (gcc_stablesort): Declare.
>
> diff --git a/gcc/sort.cc b/gcc/sort.cc
> index 9f8ee12e13b..b3be1eac72b 100644
> --- a/gcc/sort.cc
> +++ b/gcc/sort.cc
> @@ -55,6 +55,7 @@ struct sort_ctx
>    char   *out; // output buffer
>    size_t n;    // number of elements
>    size_t size; // element size
> +  size_t nlim; // limit for network sort
>  };
>
>  /* Helper for netsort. Permute, possibly in-place, 2 or 3 elements,
> @@ -178,7 +179,7 @@ do {                                  \
>  static void
>  mergesort (char *in, sort_ctx *c, size_t n, char *out, char *tmp)
>  {
> -  if (likely (n <= 5))
> +  if (likely (n <= c->nlim))
>      {
>        c->out = out;
>        c->n = n;
> @@ -221,8 +222,12 @@ gcc_qsort (void *vbase, size_t n, size_t size, cmp_fn 
> *cmp)
>  {
>    if (n < 2)
>      return;
> +  size_t nlim = 5;
> +  bool stable = (ssize_t) size < 0;
> +  if (stable)
> +    nlim = 3, size = ~size;
>    char *base = (char *)vbase;
> -  sort_ctx c = {cmp, base, n, size};
> +  sort_ctx c = {cmp, base, n, size, nlim};
>    long long scratch[32];
>    size_t bufsz = (n / 2) * size;
>    void *buf = bufsz <= sizeof scratch ? scratch : xmalloc (bufsz);
> @@ -233,3 +238,9 @@ gcc_qsort (void *vbase, size_t n, size_t size, cmp_fn 
> *cmp)
>    qsort_chk (vbase, n, size, cmp);
>  #endif
>  }
> +
> +void
> +gcc_stablesort (void *vbase, size_t n, size_t size, cmp_fn *cmp)
> +{
> +  gcc_qsort (vbase, n, ~size, cmp);
> +}
> diff --git a/gcc/system.h b/gcc/system.h
> index 203c6a4f0cf..100feb567c9 100644
> --- a/gcc/system.h
> +++ b/gcc/system.h
> @@ -1202,6 +1202,8 @@ helper_const_non_const_cast (const char *p)
>     corresponding to vec::qsort (cmp): they use C qsort internally anyway.  */
>  void qsort_chk (void *, size_t, size_t, int (*)(const void *, const void *));
>  void gcc_qsort (void *, size_t, size_t, int (*)(const void *, const void *));
> +void gcc_stablesort (void *, size_t, size_t,
> +                    int (*)(const void *, const void *));
>  #define PP_5th(a1, a2, a3, a4, a5, ...) a5
>  #undef qsort
>  #define qsort(...) PP_5th (__VA_ARGS__, gcc_qsort, 3, 2, qsort, 0) 
> (__VA_ARGS__)
> --
> 2.13.3
>

Reply via email to