Skip to content

Commit 1eb02f7

Browse files
committed
Add RISC-V RVV support for the char16_t SIMD fast path
Mirrors the SSE2/NEON backends. Enabled for the full V extension with RVV intrinsics spec 0.11+ (GCC 13+, Clang 16+). Also enables the test suite in the RISC-V CI workflow, which previously built but ran no tests, and adds a VLEN=256 QEMU pass.
1 parent a8a02f7 commit 1eb02f7

4 files changed

Lines changed: 54 additions & 3 deletions

File tree

.github/workflows/risc.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Ubuntu RISC-V rvv VLEN=128 (clang 17)
1+
name: Ubuntu RISC-V rvv (clang 17)
22

33
on: [push, pull_request]
44

@@ -14,10 +14,15 @@ jobs:
1414
- name: Build
1515
run: |
1616
CXX=clang++-17 CXXFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" \
17-
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build
17+
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -DFASTFLOAT_TEST=ON -B build
1818
cmake --build build/ -j$(nproc)
1919
- name: Test VLEN=128
2020
run: |
2121
export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu"
2222
export QEMU_CPU="rv64,v=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on"
2323
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)
24+
- name: Test VLEN=256
25+
run: |
26+
export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu"
27+
export QEMU_CPU="rv64,v=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on"
28+
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)

CONTRIBUTORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ Jan Pharago
99
Maya Warrier
1010
Taha Khokhar
1111
Anders Dalvander
12+
Fenghao Li

include/fast_float/ascii_number.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
#include <arm_neon.h>
1919
#endif
2020

21+
#ifdef FASTFLOAT_RVV
22+
#include <riscv_vector.h>
23+
#endif
24+
2125
namespace fast_float {
2226

2327
template <typename UC> fastfloat_really_inline constexpr bool has_simd_opt() {
@@ -126,6 +130,24 @@ fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
126130
FASTFLOAT_SIMD_RESTORE_WARNINGS
127131
}
128132

133+
#elif defined(FASTFLOAT_RVV)
134+
135+
fastfloat_really_inline uint64_t simd_read8_to_u64(vuint16m1_t const data) {
136+
FASTFLOAT_SIMD_DISABLE_WARNINGS
137+
vuint8mf2_t const packed = __riscv_vnsrl_wx_u8mf2(data, 0, 8);
138+
uint64_t value;
139+
__riscv_vse8_v_u8mf2(reinterpret_cast<uint8_t *>(&value), packed, 8);
140+
return value;
141+
FASTFLOAT_SIMD_RESTORE_WARNINGS
142+
}
143+
144+
fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) {
145+
FASTFLOAT_SIMD_DISABLE_WARNINGS
146+
return simd_read8_to_u64(
147+
__riscv_vle16_v_u16m1(reinterpret_cast<uint16_t const *>(chars), 8));
148+
FASTFLOAT_SIMD_RESTORE_WARNINGS
149+
}
150+
129151
#endif // FASTFLOAT_SSE2
130152

131153
// MSVC SFINAE is broken pre-VS2017
@@ -222,6 +244,22 @@ simd_parse_if_eight_digits_unrolled(char16_t const *chars,
222244
} else
223245
return false;
224246
FASTFLOAT_SIMD_RESTORE_WARNINGS
247+
#elif defined(FASTFLOAT_RVV)
248+
FASTFLOAT_SIMD_DISABLE_WARNINGS
249+
vuint16m1_t const data =
250+
__riscv_vle16_v_u16m1(reinterpret_cast<uint16_t const *>(chars), 8);
251+
252+
// (x - '0') <= 9
253+
// http://0x80.pl/articles/simd-parsing-int-sequences.html
254+
vuint16m1_t const t0 = __riscv_vsub_vx_u16m1(data, '0', 8);
255+
vbool16_t const nondigit = __riscv_vmsgtu_vx_u16m1_b16(t0, 9, 8);
256+
257+
if (__riscv_vfirst_m_b16(nondigit, 8) < 0) {
258+
i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data));
259+
return true;
260+
} else
261+
return false;
262+
FASTFLOAT_SIMD_RESTORE_WARNINGS
225263
#else
226264
static_cast<void>(chars);
227265
static_cast<void>(i);

include/fast_float/float_common.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,14 @@ using parse_options = parse_options_t<char>;
172172
#define FASTFLOAT_NEON 1
173173
#endif
174174

175-
#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON)
175+
// The RISC-V V extension guarantees VLEN >= 128. The __riscv_-prefixed
176+
// intrinsics used here require version 0.11 or later of the intrinsics spec.
177+
#if defined(__riscv_v) && defined(__riscv_v_intrinsic) && \
178+
__riscv_v_intrinsic >= 11000
179+
#define FASTFLOAT_RVV 1
180+
#endif
181+
182+
#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON) || defined(FASTFLOAT_RVV)
176183
#define FASTFLOAT_HAS_SIMD 1
177184
#endif
178185

0 commit comments

Comments
 (0)