Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 2 Aug 2026 18:04:14 +0300
From:      Konstantin Belousov <kib@freebsd.org>
To:        Robert Clausecker <fuz@freebsd.org>
Cc:        src-committers@freebsd.org, dev-commits-src-all@freebsd.org, dev-commits-src-main@freebsd.org, Minsoo Choo <minsoochoo0122@proton.me>
Subject:   Re: git: 00a79975c062 - main - libc/merge.c: use memcpy() for copying
Message-ID:  <am9cblL0Wm45xv-L@kib.kiev.ua>
In-Reply-To: <6a6f33ca.1f0f3.c2ca741@gitrepo.freebsd.org>

index | next in thread | previous in thread | raw e-mail

On Sun, Aug 02, 2026 at 12:10:50PM +0000, Robert Clausecker wrote:
> The branch main has been updated by fuz:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=00a79975c062650ba15e432e30776d42fc44fbaa
> 
> commit 00a79975c062650ba15e432e30776d42fc44fbaa
> Author:     Minsoo Choo <mchoo@FreeBSD.org>
> AuthorDate: 2026-07-02 19:47:33 +0000
> Commit:     Robert Clausecker <fuz@FreeBSD.org>
> CommitDate: 2026-08-02 11:17:45 +0000
> 
>     libc/merge.c: use memcpy() for copying
>     
>     Currently mergesort() uses ICOPY_*() to copy data as four byte blocks
>     instead of one byte. However, this is only achievable when both size and
>     base arguments are aligned to four bytes.
>     
>     Use of memcpy() is ideal as 1) it is cleaner and 2) the library will use
>     SIMD for copying when the hardware supports it. Compared to ICOPY_*(),
>     SIMD can support up to 64 bytes. When the SIMD-backed memcpy() find the
>     address is unaligned, it can first copy data up to the nearest aligned
>     address, and then use SIMD operations for faster transfer. Thus memcpy()
>     can give better performance than mergesort()'s own implementation.
>     
>     This is benchmarked on amd64 where there isn't a SIMD-backed
>     implementation yet. However, the baseline implementation in assembly
>     already delivers better performance in unaligned cases although there is
>     some performance drops in aligned cases. The benchmark results and
>     script is available in the Phabricator review. Ideally, more performance
>     improvements will come when amd64 gets SIMD implementation of memcpy().
>     
>     Signed-off-by:  Minsoo Choo <minsoochoo0122@proton.me>
>     Reviewed by:    fuz
>     MFC after:      1 week
>     Differential Revision:  https://reviews.freebsd.org/D58002
> ---
>  lib/libc/stdlib/merge.c | 69 +++++++++++++++----------------------------------
>  1 file changed, 21 insertions(+), 48 deletions(-)
> 
> diff --git a/lib/libc/stdlib/merge.c b/lib/libc/stdlib/merge.c
> index e07a3947e741..7c15fa7953f9 100644
> --- a/lib/libc/stdlib/merge.c
> +++ b/lib/libc/stdlib/merge.c
> @@ -66,25 +66,19 @@ typedef int (*cmp_t)(const void *, const void *);
>  static void setup(u_char *, u_char *, size_t, size_t, cmp_t);
>  static void insertionsort(u_char *, size_t, size_t, cmp_t);
>  
> -#define ISIZE sizeof(int)
>  #define PSIZE sizeof(u_char *)
> -#define ICOPY_LIST(src, dst, last)				\
> -	do							\
> -	*(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE;	\
> -	while(src < last)
> -#define ICOPY_ELT(src, dst, i)					\
> -	do							\
> -	*(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE;	\
> -	while (i -= ISIZE)
> -
> -#define CCOPY_LIST(src, dst, last)		\
> -	do					\
> -		*dst++ = *src++;		\
> -	while (src < last)
> -#define CCOPY_ELT(src, dst, i)			\
> -	do					\
> -		*dst++ = *src++;		\
> -	while (i -= 1)
> +#define COPY_LIST(src, dst, last)		\
> +	do {					\
> +		memcpy(dst, src, last - src);	\
> +		dst += last - src;		\
> +		src += last - src;		\
> +	} while (0)
> +#define COPY_ELT(src, dst, i)			\
> +	do {					\
> +		memcpy(dst, src, i);		\
> +		src += i;			\
> +		dst += i;			\
> +	} while (0)
>  
>  /*
>   * Find the next possible pointer head.  (Trickery for forcing an array
> @@ -112,7 +106,7 @@ mergesort(void *base, size_t nmemb, size_t size, cmp_t cmp)
>  {
>  	size_t i, nbytes, asize;
>  	int sense;
> -	int big, iflag;
> +	int big;
>  	u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
>  	u_char *list2, *list1, *p2, *p, *last, **p1;
>  
> @@ -129,10 +123,6 @@ mergesort(void *base, size_t nmemb, size_t size, cmp_t cmp)
>  		return (-1);
>  	}
>  
> -	iflag = 0;
> -	if (__is_aligned(size, ISIZE) && __is_aligned(base, ISIZE))
> -		iflag = 1;
> -
>  	if ((list2 = malloc(asize)) == NULL)
>  		return (-1);
>  
> @@ -200,34 +190,17 @@ COPY:	    			b = t;
>  	    		}
>  	    		i = size;
>  	    		if (q == f1) {
> -	    			if (iflag) {
> -	    				ICOPY_LIST(f2, tp2, b);
> -	    				ICOPY_ELT(f1, tp2, i);
> -	    			} else {
> -	    				CCOPY_LIST(f2, tp2, b);
> -	    				CCOPY_ELT(f1, tp2, i);
> -	    			}
> +	    			COPY_LIST(f2, tp2, b);
> +	    			COPY_ELT(f1, tp2, i);
>  	    		} else {
> -	    			if (iflag) {
> -	    				ICOPY_LIST(f1, tp2, b);
> -	    				ICOPY_ELT(f2, tp2, i);
> -	    			} else {
> -	    				CCOPY_LIST(f1, tp2, b);
> -	    				CCOPY_ELT(f2, tp2, i);
> -	    			}
> +	    			COPY_LIST(f1, tp2, b);
> +	    			COPY_ELT(f2, tp2, i);
The spacing is inconsistent, it is partially spaces, partially tabs,
for all additions of COPY_XXX() lines.

>  	    		}
>  	    	}
> -	    	if (f2 < l2) {
> -	    		if (iflag)
> -	    			ICOPY_LIST(f2, tp2, l2);
> -	    		else
> -	    			CCOPY_LIST(f2, tp2, l2);
> -	    	} else if (f1 < l1) {
> -	    		if (iflag)
> -	    			ICOPY_LIST(f1, tp2, l1);
> -	    		else
> -	    			CCOPY_LIST(f1, tp2, l1);
> -	    	}
> +	    	if (f2 < l2)
> +	    		COPY_LIST(f2, tp2, l2);
> +	    	else if (f1 < l1)
> +	   		COPY_LIST(f1, tp2, l1);
>  	    	*p1 = l2;
>  	    }
>  	    tp2 = list1;	/* swap list1, list2 */


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?am9cblL0Wm45xv-L>