[PATCH 0/5] RISC-V: Optimize memmove() for speed
m fally <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <[email protected]> |
This patch series optimizes the RISC-V port of memmove() for speed.
The implementation is based on the generic port of the function,
since that is what is currently used when compiling newlib for RISC-V.
In the stock implementation, an unroll-factor of 4 is used for
the word-copy-loop in the case where both source and destination
addresses are aligned on a long-boundary, and the memory areas
overlap non-destructively or not at all. No unrolling is done in
the destructive-overlap case. The proposed implementation uses an
unroll-factor of 9 for both overlap-cases when both addresses are
aligned to xlen. The unroll-factor was chosen to match memcpy() and
speeds up the copying-process for lengths >= 9*SZREG, while almost
not at all degrading performance for shorter lengths.
If at least one address is unaligned, misaligned accesses are slow
or prohibited, and there are >= 2*SZREG bytes left to copy, the
proposed implementation first aligns the source address. Then, one
whole word (or doubleword for rv64) is loaded at a time and individual
bytes are stored back to the destination. The threshold of 2*SZREG was
chosen in order to keep the negative effect on shorter copies caused
by the additional overhead of the alignment operation low.
Furthermore, the function now only uses fixed-width types.
Macros from the generic port are replaced with RISC-V-specific macros
and static inline functions.
The proposed implementation was tested on spike with pk for each of the
following configurations (compiled with gcc):
rv32ic -mtune=thead-c906 -mstrict-align -O3
rv32ic -mtune=thead-c906 -mno-strict-align -O3
rv64ic -mtune=thead-c906 -mstrict-align -O3
rv64ic -mtune=thead-c906 -mno-strict-align -O3
For each configuration, the following cases were considered when comparing
the old and new implementations:
both addresses are xlen-aligned
both addresses are unaligned
source address is xlen-aligned, destination address is not
destination address is xlen-aligned, source address is not
For each configuration, 65520 tests were run. In total, there were 67 cases
where the new implementation was slower than the original, with a maximum
difference of 10 retired instructions. In 145 cases the implementations were
equally fast. In all cases where the new implementation was slower, copied
lengths were < 32 bytes.
In all other cases, the new implementation was faster than the original.
Please see here for graphical comparisons between the two implementations:
https://cloud.servus.at/s/BA8ZJoPnE3nCtAK
Below tables show the number of cases where the new implementation was
faster, slower, or equally fast as the current implementation, as well as
the max. differences in instructions retired between the implementations.
The graphs and tables show the differences for copied lengths between
2 and 8191 bytes. For lengths < 2, old and new implementations were
equally fast.
--------- BENCHMARKING RESULTS ---------
+--------------------------------------+
| rv32ic -mstrict-align |
+--------------------------------------+
| |Number |Max. difference in |
| |of cases |instructions retired |
+------+---------+---------------------+
|Faster| 65496 | -18411 |
+------+---------+---------------------+
|Slower| 13 | 10 |
+------+---------+---------------------+
|Tied | 11 | |
+------+---------+---------------------+
+--------------------------------------+
| rv64ic -mstrict-align |
+--------------------------------------+
| |Number |Max. difference in |
| |of cases |instructions retired |
+------+---------+---------------------+
|Faster| 65509 | -21474 |
+------+---------+---------------------+
|Slower| 6 | 2 |
+------+---------+---------------------+
|Tied | 5 | |
+------+---------+---------------------+
+--------------------------------------+
| rv32ic -mno-strict-align |
+--------------------------------------+
| |Number |Max. difference in |
| |of cases |instructions retired |
+------+---------+---------------------+
|Faster| 65488 | -5231 |
+------+---------+---------------------+
|Slower| 16 | 1 |
+------+---------+---------------------+
|Tied | 16 | |
+------+---------+---------------------+
+--------------------------------------+
| rv64ic -mno-strict-align |
+--------------------------------------+
| |Number |Max. difference in |
| |of cases |instructions retired |
+------+---------+---------------------+
|Faster| 65375 | -2609 |
+------+---------+---------------------+
|Slower| 32 | 2 |
+------+---------+---------------------+
|Tied | 113 | |
+------+---------+---------------------+
m fally (5):
RISC-V: memmove() speed optimized: Add implementation
RISC-V: memmove() speed optimized: Replace macros and use fixed-width
types
RISC-V: memmove() speed optimized: Add loop-unrolling
RISC-V: memmove() speed optimized: Align source address
newlib: Regenerate configuration files
newlib/Makefile.in | 52 ++--
newlib/libc/machine/riscv/Makefile.inc | 2 +-
.../riscv/{memmove.S => memmove-asm.S} | 0
newlib/libc/machine/riscv/memmove-stub.c | 14 --
newlib/libc/machine/riscv/memmove.c | 232 ++++++++++++++++++
5 files changed, 259 insertions(+), 41 deletions(-)
rename newlib/libc/machine/riscv/{memmove.S => memmove-asm.S} (100%)
delete mode 100644 newlib/libc/machine/riscv/memmove-stub.c
create mode 100644 newlib/libc/machine/riscv/memmove.c
--
2.49.0