From: Michael Brown Date: Wed, 21 May 2025 15:12:56 +0000 (+0100) Subject: [riscv] Speed up memmove() when copying in forwards direction X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a53456334512f8de2e5d744abbc0a0cddd0eb962;p=thirdparty%2Fipxe.git [riscv] Speed up memmove() when copying in forwards direction Use the word-at-a-time variable-length memcpy() implementation when performing an overlapping copy in the forwards direction, since this is guaranteed to be safe and likely to be substantially faster than the existing bytewise copy. Signed-off-by: Michael Brown --- diff --git a/src/arch/riscv/core/riscv_string.c b/src/arch/riscv/core/riscv_string.c index 3155c3c21..e28dc8951 100644 --- a/src/arch/riscv/core/riscv_string.c +++ b/src/arch/riscv/core/riscv_string.c @@ -195,51 +195,28 @@ void riscv_memset ( void *dest, size_t len, int character ) { } /** - * Copy (possibly overlapping) memory region forwards + * Copy (possibly overlapping) memory region * * @v dest Destination region * @v src Source region * @v len Length */ -void riscv_memmove_forwards ( void *dest, const void *src, size_t len ) { +void riscv_memmove ( void *dest, const void *src, size_t len ) { + void *orig_dest = dest; unsigned long discard_data; /* Do nothing if length is zero */ if ( ! len ) return; - /* Assume memmove() is not performance-critical, and perform a - * bytewise copy for simplicity. - */ - __asm__ __volatile__ ( "\n1:\n\t" - "lb %2, (%1)\n\t" - "sb %2, (%0)\n\t" - "addi %1, %1, 1\n\t" - "addi %0, %0, 1\n\t" - "bne %0, %3, 1b\n\t" - : "+r" ( dest ), "+r" ( src ), - "=&r" ( discard_data ) - : "r" ( dest + len ) - : "memory" ); -} - -/** - * Copy (possibly overlapping) memory region backwards - * - * @v dest Destination region - * @v src Source region - * @v len Length - */ -void riscv_memmove_backwards ( void *dest, const void *src, size_t len ) { - void *orig_dest = dest; - unsigned long discard_data; - - /* Do nothing if length is zero */ - if ( ! len ) + /* Use memcpy() if copy direction is forwards */ + if ( dest <= src ) { + memcpy ( dest, src, len ); return; + } /* Assume memmove() is not performance-critical, and perform a - * bytewise copy for simplicity. + * bytewise copy backwards for simplicity. */ dest += len; src += len; @@ -254,19 +231,3 @@ void riscv_memmove_backwards ( void *dest, const void *src, size_t len ) { : "r" ( orig_dest ) : "memory" ); } - -/** - * Copy (possibly overlapping) memory region - * - * @v dest Destination region - * @v src Source region - * @v len Length - */ -void riscv_memmove ( void *dest, const void *src, size_t len ) { - - if ( dest <= src ) { - riscv_memmove_forwards ( dest, src, len ); - } else { - riscv_memmove_backwards ( dest, src, len ); - } -} diff --git a/src/arch/riscv/include/bits/string.h b/src/arch/riscv/include/bits/string.h index 3f78b351d..87834d91a 100644 --- a/src/arch/riscv/include/bits/string.h +++ b/src/arch/riscv/include/bits/string.h @@ -12,8 +12,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); extern void riscv_bzero ( void *dest, size_t len ); extern void riscv_memset ( void *dest, size_t len, int character ); extern void riscv_memcpy ( void *dest, const void *src, size_t len ); -extern void riscv_memmove_forwards ( void *dest, const void *src, size_t len ); -extern void riscv_memmove_backwards ( void *dest, const void *src, size_t len ); extern void riscv_memmove ( void *dest, const void *src, size_t len ); /** @@ -68,17 +66,12 @@ static inline __attribute__ (( always_inline )) void * memmove ( void *dest, const void *src, size_t len ) { ssize_t offset = ( dest - src ); - /* If required direction of copy is known at build time, then - * use the appropriate forwards/backwards copy directly. + /* If direction of copy is known to be forwards at build time, + * then use variable-length memcpy(). */ - if ( __builtin_constant_p ( offset ) ) { - if ( offset <= 0 ) { - riscv_memmove_forwards ( dest, src, len ); - return dest; - } else { - riscv_memmove_backwards ( dest, src, len ); - return dest; - } + if ( __builtin_constant_p ( offset ) && ( offset <= 0 ) ) { + riscv_memcpy ( dest, src, len ); + return dest; } /* Otherwise, use ambidirectional copy */