From 8ac10aeb41e420af4755c2ac84d930db7ff0134b Mon Sep 17 00:00:00 2001 From: Mason Huo Date: Tue, 21 Mar 2023 16:47:09 +0800 Subject: [PATCH] package: glibc: Add optimization memory operations for RISCV Port the memcpy & memset implementation from Linux kerenl to glibc to improve performance of memory operations in user space. Signed-off-by: Mason Huo --- ...Optimize-memory-operations-for-RISCV.patch | 270 ++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 package/glibc/2.32-50-g737efa27fca5c97f566a2005687fda7d6659cd2e/0001-Optimize-memory-operations-for-RISCV.patch diff --git a/package/glibc/2.32-50-g737efa27fca5c97f566a2005687fda7d6659cd2e/0001-Optimize-memory-operations-for-RISCV.patch b/package/glibc/2.32-50-g737efa27fca5c97f566a2005687fda7d6659cd2e/0001-Optimize-memory-operations-for-RISCV.patch new file mode 100644 index 00000000..c9053382 --- /dev/null +++ b/package/glibc/2.32-50-g737efa27fca5c97f566a2005687fda7d6659cd2e/0001-Optimize-memory-operations-for-RISCV.patch @@ -0,0 +1,270 @@ +From 15850d406a9807d70e752aacfbb456946a01f6ac Mon Sep 17 00:00:00 2001 +From: Mason Huo +Date: Tue, 21 Mar 2023 14:36:21 +0800 +Subject: [PATCH] Optimize memory operations for RISCV + +Port the memcpy & memset implementation from +Linux kerenl to glibc to improve performance of +memory operations in user space. +--- + sysdeps/riscv/memcpy.S | 120 +++++++++++++++++++++++++++++++++++++++++ + sysdeps/riscv/memset.S | 120 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 240 insertions(+) + create mode 100644 sysdeps/riscv/memcpy.S + create mode 100644 sysdeps/riscv/memset.S + +diff --git a/sysdeps/riscv/memcpy.S b/sysdeps/riscv/memcpy.S +new file mode 100644 +index 00000000..aa0eaee9 +--- /dev/null ++++ b/sysdeps/riscv/memcpy.S +@@ -0,0 +1,120 @@ ++/* memcpy for RISC-V. ++ Copyright (C) 1996-2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++ENTRY(memcpy) ++ move t6, a0 /* Preserve return value */ ++ ++ /* Defer to byte-oriented copy for small sizes */ ++ sltiu a3, a2, 128 ++ bnez a3, 4f ++ /* Use word-oriented copy only if low-order bits match */ ++ andi a3, t6, SZREG-1 ++ andi a4, a1, SZREG-1 ++ bne a3, a4, 4f ++ ++ beqz a3, 2f /* Skip if already aligned */ ++ /* ++ * Round to nearest double word-aligned address ++ * greater than or equal to start address ++ */ ++ andi a3, a1, ~(SZREG-1) ++ addi a3, a3, SZREG ++ /* Handle initial misalignment */ ++ sub a4, a3, a1 ++1: ++ lb a5, 0(a1) ++ addi a1, a1, 1 ++ sb a5, 0(t6) ++ addi t6, t6, 1 ++ bltu a1, a3, 1b ++ sub a2, a2, a4 /* Update count */ ++ ++2: ++ andi a4, a2, ~((16*SZREG)-1) ++ beqz a4, 4f ++ add a3, a1, a4 ++3: ++ REG_L a4, 0(a1) ++ REG_L a5, SZREG(a1) ++ REG_L a6, 2*SZREG(a1) ++ REG_L a7, 3*SZREG(a1) ++ REG_L t0, 4*SZREG(a1) ++ REG_L t1, 5*SZREG(a1) ++ REG_L t2, 6*SZREG(a1) ++ REG_L t3, 7*SZREG(a1) ++ REG_L t4, 8*SZREG(a1) ++ REG_L t5, 9*SZREG(a1) ++ REG_S a4, 0(t6) ++ REG_S a5, SZREG(t6) ++ REG_S a6, 2*SZREG(t6) ++ REG_S a7, 3*SZREG(t6) ++ REG_S t0, 4*SZREG(t6) ++ REG_S t1, 5*SZREG(t6) ++ REG_S t2, 6*SZREG(t6) ++ REG_S t3, 7*SZREG(t6) ++ REG_S t4, 8*SZREG(t6) ++ REG_S t5, 9*SZREG(t6) ++ REG_L a4, 10*SZREG(a1) ++ REG_L a5, 11*SZREG(a1) ++ REG_L a6, 12*SZREG(a1) ++ REG_L a7, 13*SZREG(a1) ++ REG_L t0, 14*SZREG(a1) ++ REG_L t1, 15*SZREG(a1) ++ addi a1, a1, 16*SZREG ++ REG_S a4, 10*SZREG(t6) ++ REG_S a5, 11*SZREG(t6) ++ REG_S a6, 12*SZREG(t6) ++ REG_S a7, 13*SZREG(t6) ++ REG_S t0, 14*SZREG(t6) ++ REG_S t1, 15*SZREG(t6) ++ addi t6, t6, 16*SZREG ++ bltu a1, a3, 3b ++ andi a2, a2, (16*SZREG)-1 /* Update count */ ++ ++4: ++ /* Handle trailing misalignment */ ++ beqz a2, 6f ++ add a3, a1, a2 ++ ++ /* Use word-oriented copy if co-aligned to word boundary */ ++ or a5, a1, t6 ++ or a5, a5, a3 ++ andi a5, a5, 3 ++ bnez a5, 5f ++7: ++ lw a4, 0(a1) ++ addi a1, a1, 4 ++ sw a4, 0(t6) ++ addi t6, t6, 4 ++ bltu a1, a3, 7b ++ ++ ret ++ ++5: ++ lb a4, 0(a1) ++ addi a1, a1, 1 ++ sb a4, 0(t6) ++ addi t6, t6, 1 ++ bltu a1, a3, 5b ++6: ++ ret ++END(memcpy) ++libc_hidden_builtin_def (memcpy) +diff --git a/sysdeps/riscv/memset.S b/sysdeps/riscv/memset.S +new file mode 100644 +index 00000000..431a19f5 +--- /dev/null ++++ b/sysdeps/riscv/memset.S +@@ -0,0 +1,120 @@ ++/* memset for RISC-V. ++ Copyright (C) 1996-2020 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library. If not, see ++ . */ ++ ++#include ++#include ++ ++ENTRY(memset) ++ move t0, a0 /* Preserve return value */ ++ ++ /* Defer to byte-oriented fill for small sizes */ ++ sltiu a3, a2, 16 ++ bnez a3, 4f ++ ++ /* ++ * Round to nearest XLEN-aligned address ++ * greater than or equal to start address ++ */ ++ addi a3, t0, SZREG-1 ++ andi a3, a3, ~(SZREG-1) ++ beq a3, t0, 2f /* Skip if already aligned */ ++ /* Handle initial misalignment */ ++ sub a4, a3, t0 ++1: ++ sb a1, 0(t0) ++ addi t0, t0, 1 ++ bltu t0, a3, 1b ++ sub a2, a2, a4 /* Update count */ ++ ++2: /* Duff's device with 32 XLEN stores per iteration */ ++ /* Broadcast value into all bytes */ ++ andi a1, a1, 0xff ++ slli a3, a1, 8 ++ or a1, a3, a1 ++ slli a3, a1, 16 ++ or a1, a3, a1 ++ slli a3, a1, 32 ++ or a1, a3, a1 ++ ++ /* Calculate end address */ ++ andi a4, a2, ~(SZREG-1) ++ add a3, t0, a4 ++ ++ andi a4, a4, 31*SZREG /* Calculate remainder */ ++ beqz a4, 3f /* Shortcut if no remainder */ ++ neg a4, a4 ++ addi a4, a4, 32*SZREG /* Calculate initial offset */ ++ ++ /* Adjust start address with offset */ ++ sub t0, t0, a4 ++ ++ /* Jump into loop body */ ++ /* Assumes 32-bit instruction lengths */ ++ la a5, 3f ++ srli a4, a4, 1 ++ add a5, a5, a4 ++ jr a5 ++3: ++ REG_S a1, 0(t0) ++ REG_S a1, SZREG(t0) ++ REG_S a1, 2*SZREG(t0) ++ REG_S a1, 3*SZREG(t0) ++ REG_S a1, 4*SZREG(t0) ++ REG_S a1, 5*SZREG(t0) ++ REG_S a1, 6*SZREG(t0) ++ REG_S a1, 7*SZREG(t0) ++ REG_S a1, 8*SZREG(t0) ++ REG_S a1, 9*SZREG(t0) ++ REG_S a1, 10*SZREG(t0) ++ REG_S a1, 11*SZREG(t0) ++ REG_S a1, 12*SZREG(t0) ++ REG_S a1, 13*SZREG(t0) ++ REG_S a1, 14*SZREG(t0) ++ REG_S a1, 15*SZREG(t0) ++ REG_S a1, 16*SZREG(t0) ++ REG_S a1, 17*SZREG(t0) ++ REG_S a1, 18*SZREG(t0) ++ REG_S a1, 19*SZREG(t0) ++ REG_S a1, 20*SZREG(t0) ++ REG_S a1, 21*SZREG(t0) ++ REG_S a1, 22*SZREG(t0) ++ REG_S a1, 23*SZREG(t0) ++ REG_S a1, 24*SZREG(t0) ++ REG_S a1, 25*SZREG(t0) ++ REG_S a1, 26*SZREG(t0) ++ REG_S a1, 27*SZREG(t0) ++ REG_S a1, 28*SZREG(t0) ++ REG_S a1, 29*SZREG(t0) ++ REG_S a1, 30*SZREG(t0) ++ REG_S a1, 31*SZREG(t0) ++ addi t0, t0, 32*SZREG ++ bltu t0, a3, 3b ++ andi a2, a2, SZREG-1 /* Update count */ ++ ++4: ++ /* Handle trailing misalignment */ ++ beqz a2, 6f ++ add a3, t0, a2 ++5: ++ sb a1, 0(t0) ++ addi t0, t0, 1 ++ bltu t0, a3, 5b ++6: ++ ret ++END(memset) ++libc_hidden_builtin_def (memset) +-- +2.39.2 +