riscv: optimized mem* functions
Subsystems (2)
v4 cover riscv: optimized mem* functions
From: Matteo Croce <[email protected]>
Replace the assembly mem{cpy,move,set} with C equivalent.
Try to access RAM with the largest bit width possible, but without doing unaligned accesses.
A further improvement could be to use multiple read and writes as the assembly version was trying to do.
Tested on a BeagleV Starlight with a SiFive U74 core, where the improvement is noticeable.
v3 -> v4:
- incorporate changes from proposed generic version:
https://lore.kernel.org/lkml/[email protected]/
v2 -> v3:
- alias mem* to __mem* and not viceversa
- use __alias instead of a tail call
v1 -> v2:
- reduce the threshold from 64 to 16 bytes
- fix KASAN build
- optimize memset
Matteo Croce (3):
riscv: optimized memcpy
riscv: optimized memmove
riscv: optimized memset
arch/riscv/include/asm/string.h | 18 ++-- arch/riscv/kernel/Makefile | 1 - arch/riscv/kernel/riscv_ksyms.c | 17 ---- arch/riscv/lib/Makefile | 4 +- arch/riscv/lib/memcpy.S | 108 ---------------------- arch/riscv/lib/memmove.S | 64 ------------- arch/riscv/lib/memset.S | 113 ----------------------- arch/riscv/lib/string.c | 154 ++++++++++++++++++++++++++++++++ 8 files changed, 164 insertions(+), 315 deletions(-) delete mode 100644 arch/riscv/kernel/riscv_ksyms.c delete mode 100644 arch/riscv/lib/memcpy.S delete mode 100644 arch/riscv/lib/memmove.S delete mode 100644 arch/riscv/lib/memset.S create mode 100644 arch/riscv/lib/string.c
Signature · 1 line
2.31.1
PATCH v4 1/3 riscv: optimized memcpy
From: Matteo Croce <[email protected]>
Write a C version of memcpy() which uses the biggest data size allowed, without generating unaligned accesses.
The procedure is made of three steps:
First copy data one byte at time until the destination buffer is aligned to a long boundary.
Then copy the data one long at time shifting the current and the next u8 to compose a long at every cycle.
Finally, copy the remainder one byte at time.
On a BeagleV, the TCP RX throughput increased by 45%:
before:
$ iperf3 -c beaglev Connecting to host beaglev, port 5201 [ 5] local 192.168.85.6 port 44840 connected to 192.168.85.48 port 5201 [ ID] Interval Transfer Bitrate Retr Cwnd [ 5] 0.00-1.00 sec 76.4 MBytes 641 Mbits/sec 27 624 KBytes [ 5] 1.00-2.00 sec 72.5 MBytes 608 Mbits/sec 0 708 KBytes [ 5] 2.00-3.00 sec 73.8 MBytes 619 Mbits/sec 10 451 KBytes [ 5] 3.00-4.00 sec 72.5 MBytes 608 Mbits/sec 0 564 KBytes [ 5] 4.00-5.00 sec 73.8 MBytes 619 Mbits/sec 0 658 KBytes [ 5] 5.00-6.00 sec 73.8 MBytes 619 Mbits/sec 14 522 KBytes [ 5] 6.00-7.00 sec 73.8 MBytes 619 Mbits/sec 0 621 KBytes [ 5] 7.00-8.00 sec 72.5 MBytes 608 Mbits/sec 0 706 KBytes [ 5] 8.00-9.00 sec 73.8 MBytes 619 Mbits/sec 20 580 KBytes [ 5] 9.00-10.00 sec 73.8 MBytes 619 Mbits/sec 0 672 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 736 MBytes 618 Mbits/sec 71 sender [ 5] 0.00-10.01 sec 733 MBytes 615 Mbits/sec receiver
after:
$ iperf3 -c beaglev Connecting to host beaglev, port 5201 [ 5] local 192.168.85.6 port 44864 connected to 192.168.85.48 port 5201 [ ID] Interval Transfer Bitrate Retr Cwnd [ 5] 0.00-1.00 sec 109 MBytes 912 Mbits/sec 48 559 KBytes [ 5] 1.00-2.00 sec 108 MBytes 902 Mbits/sec 0 690 KBytes [ 5] 2.00-3.00 sec 106 MBytes 891 Mbits/sec 36 396 KBytes [ 5] 3.00-4.00 sec 108 MBytes 902 Mbits/sec 0 567 KBytes [ 5] 4.00-5.00 sec 106 MBytes 891 Mbits/sec 0 699 KBytes [ 5] 5.00-6.00 sec 106 MBytes 891 Mbits/sec 32 414 KBytes [ 5] 6.00-7.00 sec 106 MBytes 891 Mbits/sec 0 583 KBytes [ 5] 7.00-8.00 sec 106 MBytes 891 Mbits/sec 0 708 KBytes [ 5] 8.00-9.00 sec 106 MBytes 891 Mbits/sec 28 433 KBytes [ 5] 9.00-10.00 sec 108 MBytes 902 Mbits/sec 0 591 KBytes - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bitrate Retr [ 5] 0.00-10.00 sec 1.04 GBytes 897 Mbits/sec 144 sender [ 5] 0.00-10.01 sec 1.04 GBytes 894 Mbits/sec receiver
And the decreased CPU time of the memcpy() is observable with perf top. This is the perf top -Ue task-clock output when doing the test:
before:
Overhead Shared O Symbol 42.22% [kernel] [k] memcpy 35.00% [kernel] [k] __asm_copy_to_user 3.50% [kernel] [k] sifive_l2_flush64_range 2.30% [kernel] [k] stmmac_napi_poll_rx 1.11% [kernel] [k] memset
after:
Overhead Shared O Symbol 45.69% [kernel] [k] __asm_copy_to_user 29.06% [kernel] [k] memcpy 4.09% [kernel] [k] sifive_l2_flush64_range 2.77% [kernel] [k] stmmac_napi_poll_rx 1.24% [kernel] [k] memset
--- arch/riscv/include/asm/string.h | 8 ++- arch/riscv/kernel/riscv_ksyms.c | 2 - arch/riscv/lib/Makefile | 2 +- arch/riscv/lib/memcpy.S | 108 -------------------------------- arch/riscv/lib/string.c | 90 ++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 113 deletions(-) delete mode 100644 arch/riscv/lib/memcpy.S create mode 100644 arch/riscv/lib/string.c
arch/riscv/include/asm/string.h +6 -2
@@ -12,9 +12,13 @@#define __HAVE_ARCH_MEMSET extern asmlinkage void *memset(void *, int, size_t); extern asmlinkage void *__memset(void *, int, size_t); + +#ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE #define __HAVE_ARCH_MEMCPY -extern asmlinkage void *memcpy(void *, const void *, size_t); -extern asmlinkage void *__memcpy(void *, const void *, size_t); +extern void *memcpy (void *dest,const void *src,size_t count); +extern void *__memcpy (void *dest,const void *src,size_t count); +#endif +#define __HAVE_ARCH_MEMMOVE extern asmlinkage void *memmove(void *, const void *, size_t); extern asmlinkage void *__memmove(void *, const void *, size_t);
arch/riscv/kernel/riscv_ksyms.c +0 -2
@@ -10,8 +10,6 @@* Assembly functions that may be used (directly or indirectly) by modules */ EXPORT_SYMBOL (memset); -EXPORT_SYMBOL (memcpy);EXPORT_SYMBOL (memmove);EXPORT_SYMBOL (__memset); -EXPORT_SYMBOL (__memcpy);EXPORT_SYMBOL (__memmove);
arch/riscv/lib/Makefile +1 -1
@@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only lib-y += delay.o -lib-y += memcpy.o lib-y += memset.o lib-y += memmove.o lib-$(CONFIG_MMU) += uaccess.o lib-$(CONFIG_64BIT) += tishift.o +lib-$(CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE) += string.o obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
arch/riscv/lib/memcpy.S deleted +0 -108
108 lines not on this page · raw message
arch/riscv/lib/string.c new file +90 -0
90 lines not on this page · raw message
Signature · 1 line
2.31.1
PATCH v4 2/3 riscv: optimized memmove
In reply to Matteo CroceFrom: Matteo Croce <[email protected]>
When the destination buffer is before the source one, or when the buffers doesn't overlap, it's safe to use memcpy() instead, which is optimized to use a bigger data size possible.
--- arch/riscv/include/asm/string.h | 6 ++-- arch/riscv/kernel/riscv_ksyms.c | 2 -- arch/riscv/lib/Makefile | 1 - arch/riscv/lib/memmove.S | 64 --------------------------------- arch/riscv/lib/string.c | 23 ++++++++++++ 5 files changed, 26 insertions(+), 70 deletions(-) delete mode 100644 arch/riscv/lib/memmove.S
arch/riscv/include/asm/string.h +3 -3
@@ -17,11 +17,11 @@ extern asmlinkage void *__memset(void *, int, size_t);#define __HAVE_ARCH_MEMCPYextern void *memcpy (void *dest,const void *src,size_t count);extern void *__memcpy (void *dest,const void *src,size_t count); +#define __HAVE_ARCH_MEMMOVE +extern void *memmove (void *dest,const void *src,size_t count); +extern void *__memmove (void *dest,const void *src,size_t count);#endif -#define __HAVE_ARCH_MEMMOVE -extern asmlinkage void *memmove(void *, const void *, size_t); -extern asmlinkage void *__memmove(void *, const void *, size_t);/* For those files which don't want to check by kasan. */ #if defined(CONFIG_KASAN ) && !defined(__SANITIZE_ADDRESS__)#define memcpy (dst, src, len) __memcpy(dst, src, len)
arch/riscv/kernel/riscv_ksyms.c +0 -2
@@ -10,6 +10,4 @@* Assembly functions that may be used (directly or indirectly) by modules */ EXPORT_SYMBOL (memset); -EXPORT_SYMBOL (memmove);EXPORT_SYMBOL (__memset); -EXPORT_SYMBOL (__memmove);
arch/riscv/lib/Makefile +0 -1
@@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only lib-y += delay.o lib-y += memset.o -lib-y += memmove.o lib-$(CONFIG_MMU) += uaccess.o lib-$(CONFIG_64BIT) += tishift.o lib-$(CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE) += string.o
arch/riscv/lib/memmove.S deleted +0 -64
64 lines not on this page · raw message
arch/riscv/lib/string.c +23 -0
@@ -88,3 +88,26 @@ EXPORT_SYMBOL(__memcpy);void *memcpy (void *dest,const void *src,size_t count)__weak __alias (__memcpy);EXPORT_SYMBOL (memcpy); + +/* +* Simply check if the buffer overlaps an call memcpy() in case, +* otherwise do a simple one byte at time backward copy. +*/ +void *__memmove (void *dest,const void *src,size_t count) +{ +if (dest < src || src + count <= dest) +return memcpy (dest, src, count); + +if (dest > src) { +const char *s = src + count; +char *tmp = dest + count; + +while (count--) + *--tmp = *--s; + } +return dest; +} +EXPORT_SYMBOL (__memmove); + +void *memmove (void *dest,const void *src,size_t count)__weak __alias (__memmove); +EXPORT_SYMBOL (memmove);
Signature · 1 line
2.31.1
kernel test robot
build botRe: [PATCH v4 2/3] riscv: optimized memmove
Thank you for the patch! Yet something to improve:
Hi Matteo,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linux/master]
[also build test ERROR on linus/master v5.15-rc1 next-20210917] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Matteo-Croce/riscv-optimized-mem-functions/20210920-032303 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git bdb575f872175ed0ecf2638369da1cb7a6e86a14 config: riscv-randconfig-r004-20210919 (attached as .config) compiler: riscv64-linux-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/9a948fd7d78a58890608e9dd0f77e5ff84f36e3e
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Matteo-Croce/riscv-optimized-mem-functions/20210920-032303 git checkout 9a948fd7d78a58890608e9dd0f77e5ff84f36e3e
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bash
If you fix the issue, kindly add following tag as appropriate
All errors (new ones prefixed by >>):
arch/riscv/lib/string.c: In function '__memmove':
>> arch/riscv/lib/string.c:89:7: error: inlining failed in call to 'always_inline' 'memcpy': function body can be overwritten at link time
89 | void *memcpy(void *dest, const void *src, size_t count) __weak __alias(__memcpy);
| ^~~~~~
arch/riscv/lib/string.c:99:24: note: called from here
99 | return memcpy(dest, src, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~vim +89 arch/riscv/lib/string.c
86c5866e9b7fdd Matteo Croce 2021-09-19 8886c5866e9b7fdd Matteo Croce 2021-09-19 @89 void *memcpy(void *dest, const void *src, size_t count) __weak __alias(__memcpy); 86c5866e9b7fdd Matteo Croce 2021-09-19 90 EXPORT_SYMBOL(memcpy);9a948fd7d78a58 Matteo Croce 2021-09-19 91
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Re: [PATCH v4 2/3] riscv: optimized memmove
Quoted 42 lines · kernel test robot
Hi Matteo,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linux/master]
[also build test ERROR on linus/master v5.15-rc1 next-20210917] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]url: https://github.com/0day-ci/linux/commits/Matteo-Croce/riscv-optimized-mem-functions/20210920-032303 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git bdb575f872175ed0ecf2638369da1cb7a6e86a14 config: riscv-randconfig-r004-20210919 (attached as .config) compiler: riscv64-linux-gcc (GCC) 11.2.0reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/9a948fd7d78a58890608e9dd0f77e5ff84f36e3e
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Matteo-Croce/riscv-optimized-mem-functions/20210920-032303 git checkout9a948fd7d78a58890608e9dd0f77e5ff84f36e3e
# save the attached .config to linux build tree
mkdirbuild_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bashIf you fix the issue, kindly add following tag as appropriate
Reported-by kernel test robot <[email protected]>All errors (new ones prefixed by >>):
arch/riscv/lib/string.c: In function '__memmove':Quoted 1 line
Quoted 1 line
arch/riscv/lib/string.c:89:7: error: inlining failed in call to 'always_inline' 'memcpy': function body can be overwritten at link time89 | void *memcpy(void *dest, const void *src, size_t count) __weak __alias(__memcpy); | ^~~~~~ arch/riscv/lib/string.c:99:24: note: called from here 99 | return memcpy(dest, src, count); | ^~~~~~~~~~~~~~~~~~~~~~~~vim +89
arch/riscv/lib/string.c
Quoted 8 lines
86c5866e9b7fddMatteo Croce 2021-09-19 8886c5866e9b7fddMatteo Croce 2021-09-19 @89 void *memcpy(void *dest, const void *src,size_tcount)__weak__alias(__memcpy);86c5866e9b7fddMatteo Croce 2021-09-19 90EXPORT_SYMBOL(memcpy);9a948fd7d78a58Matteo Croce 2021-09-19 91---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
How can we fix this? Maybe calling __memcpy() instead?
Signature · 1 line
per aspera ad upstream
Re: [PATCH v4 2/3] riscv: optimized memmove
Quoted 49 lines · Matteo Croce
Quoted 47 lines · kernel test robot
Hi Matteo,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linux/master]
[also build test ERROR on linus/master v5.15-rc1 next-20210917] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]url: https://github.com/0day-ci/linux/commits/Matteo-Croce/riscv-optimized-mem-functions/20210920-032303 base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git bdb575f872175ed0ecf2638369da1cb7a6e86a14 config: riscv-randconfig-r004-20210919 (attached as .config) compiler: riscv64-linux-gcc (GCC) 11.2.0reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/9a948fd7d78a58890608e9dd0f77e5ff84f36e3e
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Matteo-Croce/riscv-optimized-mem-functions/20210920-032303 git checkout9a948fd7d78a58890608e9dd0f77e5ff84f36e3e
# save the attached .config to linux build tree
mkdirbuild_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=riscv SHELL=/bin/bashIf you fix the issue, kindly add following tag as appropriate
Reported-by kernel test robot <[email protected]>All errors (new ones prefixed by >>):
arch/riscv/lib/string.c: In function '__memmove':Quoted 1 line
Quoted 1 line
arch/riscv/lib/string.c:89:7: error: inlining failed in call to 'always_inline' 'memcpy': function body can be overwritten at link time89 | void *memcpy(void *dest, const void *src, size_t count) __weak __alias(__memcpy); | ^~~~~~ arch/riscv/lib/string.c:99:24: note: called from here 99 | return memcpy(dest, src, count); | ^~~~~~~~~~~~~~~~~~~~~~~~vim +89
arch/riscv/lib/string.c
86c5866e9b7fddMatteo Croce 2021-09-19 8886c5866e9b7fddMatteo Croce 2021-09-19 @89 void *memcpy(void *dest, const void *src,size_tcount)__weak__alias(__memcpy);86c5866e9b7fddMatteo Croce 2021-09-19 90EXPORT_SYMBOL(memcpy);9a948fd7d78a58Matteo Croce 2021-09-19 91
Quoted 5 lines
Quoted 3 lines
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.orgHow can we fix this? Maybe calling
__memcpy()instead?
Yes, that fixes building with CONFIG_FORTIFY_SOURCE=y for me. Kasan already wraps memmove itself, so it should be fine to call __memcpy directly.
/Emil
PATCH v4 3/3 riscv: optimized memset
In reply to Matteo CroceFrom: Matteo Croce <[email protected]>
The generic memset is defined as a byte at time write. This is always safe, but it's slower than a 4 byte or even 8 byte write.
Write a generic memset which fills the data one byte at time until the destination is aligned, then fills using the largest size allowed, and finally fills the remaining data one byte at time.
--- arch/riscv/include/asm/string.h | 10 +-- arch/riscv/kernel/Makefile | 1 - arch/riscv/kernel/riscv_ksyms.c | 13 ---- arch/riscv/lib/Makefile | 1 - arch/riscv/lib/memset.S | 113 -------------------------------- arch/riscv/lib/string.c | 41 ++++++++++++ 6 files changed, 44 insertions(+), 135 deletions(-) delete mode 100644 arch/riscv/kernel/riscv_ksyms.c delete mode 100644 arch/riscv/lib/memset.S
arch/riscv/include/asm/string.h +3 -7
@@ -6,14 +6,10 @@#ifndef _ASM_RISCV_STRING_H#define _ASM_RISCV_STRING_H -#include <linux/types.h> -#include <linux/linkage.h> - -#define __HAVE_ARCH_MEMSET -extern asmlinkage void *memset(void *, int, size_t); -extern asmlinkage void *__memset(void *, int, size_t); -#ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE +#define __HAVE_ARCH_MEMSET +extern void *memset (void *s,int c,size_t count); +extern void *__memset (void *s,int c,size_t count);#define __HAVE_ARCH_MEMCPYextern void *memcpy (void *dest,const void *src,size_t count);extern void *__memcpy (void *dest,const void *src,size_t count);
arch/riscv/kernel/Makefile +0 -1
@@ -31,7 +31,6 @@ obj-y += syscall_table.o obj-y += sys_riscv.o obj-y += time.o obj-y += traps.o -obj-y += riscv_ksyms.o obj-y += stacktrace.o obj-y += cacheinfo.o obj-y += patch.o
arch/riscv/kernel/riscv_ksyms.c deleted +0 -13
@@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -* Copyright (C) 2017 Zihao Yu -*/ - -#include <linux/export.h> -#include <linux/uaccess.h> - -/* -* Assembly functions that may be used (directly or indirectly) by modules -*/ -EXPORT_SYMBOL (memset); -EXPORT_SYMBOL (__memset);
arch/riscv/lib/Makefile +0 -1
@@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only lib-y += delay.o -lib-y += memset.o lib-$(CONFIG_MMU) += uaccess.o lib-$(CONFIG_64BIT) += tishift.o lib-$(CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE) += string.o
arch/riscv/lib/memset.S deleted +0 -113
113 lines not on this page · raw message
arch/riscv/lib/string.c +41 -0
44 lines not on this page · raw message
Signature · 1 line
2.31.1
Quoted 11 lines · Matteo Croce
From: Matteo Croce <[email protected]>
Replace the assembly mem{cpy,move,set} with C equivalent.
Try to access RAM with the largest bit width possible, but without doing unaligned accesses.
A further improvement could be to use multiple read and writes as the assembly version was trying to do.
Quoted 7 lines
Tested on a BeagleV Starlight with a SiFive U74 core, where the improvement is noticeable.
v3 -> v4:
- incorporate changes from proposed generic version:
https://lore.kernel.org/lkml/[email protected]/
Sorry, the correct link is:
https://lore.kernel.org/lkml/[email protected]/
Signature · 1 line
per aspera ad upstream
Palmer Dabbelt
maintainerQuoted 31 lines · On Sun, 19 Sep 2021 12:21:01 PDT (-0700), [email protected] wrote:
From: Matteo Croce <[email protected]>
Replace the assembly mem{cpy,move,set} with C equivalent.
Try to access RAM with the largest bit width possible, but without doing unaligned accesses.
A further improvement could be to use multiple read and writes as the assembly version was trying to do.
Tested on a BeagleV Starlight with a SiFive U74 core, where the improvement is noticeable.
v3 -> v4:
- incorporate changes from proposed generic version:
https://lore.kernel.org/lkml/[email protected]/v2 -> v3:
- alias mem* to __mem* and not viceversa
- use__aliasinstead of a tail callv1 -> v2:
- reduce the threshold from 64 to 16 bytes
- fix KASAN build
- optimize memsetMatteo Croce (3):
riscv: optimized memcpy
riscv: optimized memmove
riscv: optimized memset
Quoted 14 lines
arch/riscv/include/asm/string.h | 18 ++-- arch/riscv/kernel/Makefile | 1 - arch/riscv/kernel/riscv_ksyms.c | 17 ---- arch/riscv/lib/Makefile | 4 +- arch/riscv/lib/memcpy.S | 108 ---------------------- arch/riscv/lib/memmove.S | 64 ------------- arch/riscv/lib/memset.S | 113 ----------------------- arch/riscv/lib/string.c | 154 ++++++++++++++++++++++++++++++++ 8 files changed, 164 insertions(+), 315 deletions(-) delete mode 100644 arch/riscv/kernel/riscv_ksyms.c delete mode 100644 arch/riscv/lib/memcpy.S delete mode 100644 arch/riscv/lib/memmove.S delete mode 100644 arch/riscv/lib/memset.S create mode 100644 arch/riscv/lib/string.c
Thanks. These generally look good, but they're failing to build for me. I'm getting errors along the lines of
arch/riscv/lib/string.c:89:7: error: inlining failed in call to ‘always_inline’ ‘memcpy’: function body can be overwritten at link time
89 | void *memcpy(void *dest, const void *src, size_t count) __weak __alias(__memcpy); | ^~~~~~
arch/riscv/lib/string.c:99:10: note: called from here
99 | return memcpy(dest, src, count);
| ^~~~~~~~~~~~~~~~~~~~~~~~I'm still a bit behind on email so I'm going to keep going through patches, but if there's no v5 by the time I get back here then I'll take a look.
Quoted 57 lines · Palmer Dabbelt
Quoted 31 lines · On Sun, 19 Sep 2021 12:21:01 PDT (-0700), [email protected] wrote:
From: Matteo Croce <[email protected]>
Replace the assembly mem{cpy,move,set} with C equivalent.
Try to access RAM with the largest bit width possible, but without doing unaligned accesses.
A further improvement could be to use multiple read and writes as the assembly version was trying to do.
Tested on a BeagleV Starlight with a SiFive U74 core, where the improvement is noticeable.
v3 -> v4:
- incorporate changes from proposed generic version:
https://lore.kernel.org/lkml/[email protected]/v2 -> v3:
- alias mem* to __mem* and not viceversa
- use__aliasinstead of a tail callv1 -> v2:
- reduce the threshold from 64 to 16 bytes
- fix KASAN build
- optimize memsetMatteo Croce (3):
riscv: optimized memcpy
riscv: optimized memmove
riscv: optimized memsetQuoted 14 lines
arch/riscv/include/asm/string.h | 18 ++-- arch/riscv/kernel/Makefile | 1 - arch/riscv/kernel/riscv_ksyms.c | 17 ---- arch/riscv/lib/Makefile | 4 +- arch/riscv/lib/memcpy.S | 108 ---------------------- arch/riscv/lib/memmove.S | 64 ------------- arch/riscv/lib/memset.S | 113 ----------------------- arch/riscv/lib/string.c | 154 ++++++++++++++++++++++++++++++++ 8 files changed, 164 insertions(+), 315 deletions(-) delete mode 100644 arch/riscv/kernel/riscv_ksyms.c delete mode 100644 arch/riscv/lib/memcpy.S delete mode 100644 arch/riscv/lib/memmove.S delete mode 100644 arch/riscv/lib/memset.S create mode 100644 arch/riscv/lib/string.cThanks. These generally look good, but they're failing to build for me. I'm getting errors along the lines of
arch/riscv/lib/string.c:89:7: error: inlining failed in call to ‘always_inline’ ‘memcpy’: function body can be overwritten at link time 89 | void *memcpy(void *dest, const void *src, size_t count) __weak __alias(__memcpy); | ^~~~~~ arch/riscv/lib/string.c:99:10: note: called from here 99 | return memcpy(dest, src, count); | ^~~~~~~~~~~~~~~~~~~~~~~~
Quoted 3 lines
I'm still a bit behind on email so I'm going to keep going through patches, but if there's no v5 by the time I get back here then I'll take a look.
I've sent a v5 here:
https://lore.kernel.org/linux-riscv/[email protected]/
Regards,
Signature · 1 line
per aspera ad upstream