public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] stdlib: Avoid element self-comparisons in qsort
@ 2023-11-07 16:10 Florian Weimer
  2023-11-08 13:10 ` Adhemerval Zanella Netto
  0 siblings, 1 reply; 2+ messages in thread
From: Florian Weimer @ 2023-11-07 16:10 UTC (permalink / raw)
  To: libc-alpha

This improves compatibility with applications which assume that qsort
does not invoke the comparison function with equal pointer arguments.

The newly introduced branches should be predictable, as leading to a
call to the comparison function.  If the prediction fails, we avoid
calling the function.

Tested on x86_64-linux-gnu.  I don't know if it papers over the LLVM
problem, but the line number in the posted backtrace for the assertion
failure points to the first while statement that the patch changes.

Thanks,
Florian

---
 stdlib/qsort.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/stdlib/qsort.c b/stdlib/qsort.c
index fd32a165e7..ad110e8a89 100644
--- a/stdlib/qsort.c
+++ b/stdlib/qsort.c
@@ -136,7 +136,7 @@ siftdown (void *base, size_t size, size_t k, size_t n,
       if (j < n && cmp (base + (j * size), base + ((j + 1) * size), arg) < 0)
 	j++;
 
-      if (cmp (base + (k * size), base + (j * size), arg) >= 0)
+      if (j == k || cmp (base + (k * size), base + (j * size), arg) >= 0)
 	break;
 
       do_swap (base + (size * j), base + (k * size), size, swap_type);
@@ -332,10 +332,12 @@ __qsort_r (void *const pbase, size_t total_elems, size_t size,
 	     that this algorithm runs much faster than others. */
 	  do
 	    {
-	      while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
+	      while (left_ptr != mid
+		     && (*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
 		left_ptr += size;
 
-	      while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
+	      while (right_ptr != mid
+		     && (*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
 		right_ptr -= size;
 
 	      if (left_ptr < right_ptr)

base-commit: 5dd3bda59c2d9da138f0d98808d087cdb95cdc17


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] stdlib: Avoid element self-comparisons in qsort
  2023-11-07 16:10 [PATCH] stdlib: Avoid element self-comparisons in qsort Florian Weimer
@ 2023-11-08 13:10 ` Adhemerval Zanella Netto
  0 siblings, 0 replies; 2+ messages in thread
From: Adhemerval Zanella Netto @ 2023-11-08 13:10 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha



On 07/11/23 13:10, Florian Weimer wrote:
> This improves compatibility with applications which assume that qsort
> does not invoke the comparison function with equal pointer arguments.
> 
> The newly introduced branches should be predictable, as leading to a
> call to the comparison function.  If the prediction fails, we avoid
> calling the function.
> 
> Tested on x86_64-linux-gnu.  I don't know if it papers over the LLVM
> problem, but the line number in the posted backtrace for the assertion
> failure points to the first while statement that the patch changes.
> 
> Thanks,
> Florian
> 

LGTM, thanks.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>

> ---
>  stdlib/qsort.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/stdlib/qsort.c b/stdlib/qsort.c
> index fd32a165e7..ad110e8a89 100644
> --- a/stdlib/qsort.c
> +++ b/stdlib/qsort.c
> @@ -136,7 +136,7 @@ siftdown (void *base, size_t size, size_t k, size_t n,
>        if (j < n && cmp (base + (j * size), base + ((j + 1) * size), arg) < 0)
>  	j++;
>  
> -      if (cmp (base + (k * size), base + (j * size), arg) >= 0)
> +      if (j == k || cmp (base + (k * size), base + (j * size), arg) >= 0)
>  	break;
>  
>        do_swap (base + (size * j), base + (k * size), size, swap_type);
> @@ -332,10 +332,12 @@ __qsort_r (void *const pbase, size_t total_elems, size_t size,
>  	     that this algorithm runs much faster than others. */
>  	  do
>  	    {
> -	      while ((*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
> +	      while (left_ptr != mid
> +		     && (*cmp) ((void *) left_ptr, (void *) mid, arg) < 0)
>  		left_ptr += size;
>  
> -	      while ((*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
> +	      while (right_ptr != mid
> +		     && (*cmp) ((void *) mid, (void *) right_ptr, arg) < 0)
>  		right_ptr -= size;
>  
>  	      if (left_ptr < right_ptr)
> 
> base-commit: 5dd3bda59c2d9da138f0d98808d087cdb95cdc17
> 

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-11-08 13:10 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-07 16:10 [PATCH] stdlib: Avoid element self-comparisons in qsort Florian Weimer
2023-11-08 13:10 ` Adhemerval Zanella Netto

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).