mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
add rvv-vls backend (#2593)
This commit is contained in:
@@ -19,11 +19,11 @@ jobs:
|
||||
sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-18
|
||||
- name: Build
|
||||
run: |
|
||||
CXX=clang++-18 CXXFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvbb" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||
cmake --build build/ -j$(nproc)
|
||||
CC=clang-18 CXX=clang++-18 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvbb" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build
|
||||
cmake --build build/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=1024
|
||||
run: |
|
||||
export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu"
|
||||
export QEMU_CPU="rv64,v=on,zvbb=on,vlen=1024,rvv_ta_all_1s=on,rvv_ma_all_1s=on"
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,zvbb=on,vlen=1024,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)
|
||||
|
||||
@@ -19,11 +19,6 @@ jobs:
|
||||
sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-17
|
||||
- name: Build
|
||||
run: |
|
||||
CXX=clang++-17 CXXFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||
cmake --build build/ -j$(nproc)
|
||||
- name: Test VLEN=128
|
||||
run: |
|
||||
export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu"
|
||||
export QEMU_CPU="rv64,v=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on"
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)
|
||||
CC=clang-17 CXX=clang++-17 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build
|
||||
cmake --build build/ -j$(nproc) --config Release
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Ubuntu rvv VLEN=128 (clang 20)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update -q -y
|
||||
sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-20
|
||||
- name: Build
|
||||
run: |
|
||||
CC=clang-20 CXX=clang++-20 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build
|
||||
cmake --build build/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=128
|
||||
run: |
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)
|
||||
- name: Build VLS
|
||||
run: |
|
||||
CC=clang-20 CXX=clang++-20 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvl128b_zba_zbb_zbc -mrvv-vector-bits=zvl" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build-vls
|
||||
cmake --build build-vls/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=128 VLS
|
||||
run: |
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,zba=on,zbb=on,zbc=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build-vls -j $(nproc)
|
||||
@@ -19,11 +19,21 @@ jobs:
|
||||
sudo apt-get install -y cmake make g++-14-riscv64-linux-gnu qemu-user-static
|
||||
- name: Build
|
||||
run: |
|
||||
CXX=riscv64-linux-gnu-g++-14 CXXFLAGS=-march=rv64gcv \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build
|
||||
cmake --build build/ -j$(nproc)
|
||||
CC=riscv64-linux-gnu-gcc-14 CXX=riscv64-linux-gnu-g++-14 CFLAGS=-march=rv64gcv CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build
|
||||
cmake --build build/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=256
|
||||
run: |
|
||||
export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu"
|
||||
export QEMU_CPU="rv64,v=on,zvbb=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on"
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,zvbb=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)
|
||||
- name: Build VLS
|
||||
run: |
|
||||
CC=riscv64-linux-gnu-gcc-14 CXX=riscv64-linux-gnu-g++-14 CFLAGS="-march=rv64gcv_zvl256b -mrvv-vector-bits=zvl" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build-vls
|
||||
cmake --build build-vls/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=256 VLS
|
||||
run: |
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,zvbb=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build-vls -j $(nproc)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
name: Ubuntu rvv VLEN=512 (clang 19)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt-get update -q -y
|
||||
sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-19
|
||||
- name: Build
|
||||
run: |
|
||||
CC=clang-19 CXX=clang++-19 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build
|
||||
cmake --build build/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=512
|
||||
run: |
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,vlen=512,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc)
|
||||
- name: Build VLS
|
||||
run: |
|
||||
CC=clang-19 CXX=clang++-19 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvl512b_zba_zbb_zbc -mrvv-vector-bits=zvl" CXXFLAGS="${CFLAGS}" \
|
||||
cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build-vls
|
||||
cmake --build build-vls/ -j$(nproc) --config Release
|
||||
- name: Test VLEN=512 VLS
|
||||
run: |
|
||||
QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \
|
||||
QEMU_CPU="rv64,v=on,zba=on,zbb=on,zbc=on,vlen=512,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \
|
||||
ctest --timeout 1800 --output-on-failure --test-dir build-vls -j $(nproc)
|
||||
@@ -428,6 +428,7 @@ namespace {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 4, "ARM kernel should use four registers per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "simdjson/lasx.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lsx)
|
||||
#include "simdjson/lsx.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls)
|
||||
#include "simdjson/rvv-vls.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
@@ -21,6 +21,8 @@ namespace simdjson {
|
||||
namespace lsx {}
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
|
||||
namespace lasx {}
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls)
|
||||
namespace rvv_vls {}
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "simdjson/lsx/builder.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
|
||||
#include "simdjson/lasx/builder.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls)
|
||||
#include "simdjson/rvv-vls/builder.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
@@ -37,4 +39,4 @@ namespace simdjson {
|
||||
namespace builder = SIMDJSON_BUILTIN_IMPLEMENTATION::builder;
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_BUILTIN_BUILDER_H
|
||||
#endif // SIMDJSON_BUILTIN_BUILDER_H
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "simdjson/lsx/implementation.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
|
||||
#include "simdjson/lasx/implementation.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls)
|
||||
#include "simdjson/rvv-vls/implementation.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
@@ -39,4 +41,4 @@ namespace simdjson {
|
||||
const implementation * builtin_implementation();
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H
|
||||
#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "simdjson/lsx/ondemand.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
|
||||
#include "simdjson/lasx/ondemand.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls)
|
||||
#include "simdjson/rvv-vls/ondemand.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
@@ -37,4 +39,4 @@ namespace simdjson {
|
||||
namespace ondemand = SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand;
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_BUILTIN_ONDEMAND_H
|
||||
#endif // SIMDJSON_BUILTIN_ONDEMAND_H
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "simdjson/lasx/begin.h"
|
||||
#elif SIMDJSON_IMPLEMENTATION_LSX
|
||||
#include "simdjson/lsx/begin.h"
|
||||
#elif SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
#include "simdjson/rvv-vls/begin.h"
|
||||
#elif SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
#include "simdjson/fallback/begin.h"
|
||||
#else
|
||||
@@ -48,4 +50,4 @@ enum class number_type {
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_GENERIC_BASE_H
|
||||
#endif // SIMDJSON_GENERIC_BASE_H
|
||||
|
||||
@@ -300,6 +300,7 @@ namespace simd {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 2, "Haswell kernel should use two registers per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
|
||||
@@ -322,6 +322,7 @@ namespace simd {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 1, "Icelake kernel should use one register per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#define SIMDJSON_IMPLEMENTATION_ID_westmere 6
|
||||
#define SIMDJSON_IMPLEMENTATION_ID_lsx 7
|
||||
#define SIMDJSON_IMPLEMENTATION_ID_lasx 8
|
||||
//#define SIMDJSON_IMPLEMENTATION_ID_rvv 9
|
||||
#define SIMDJSON_IMPLEMENTATION_ID_rvv_vls 10
|
||||
|
||||
#define SIMDJSON_IMPLEMENTATION_ID_FOR(IMPL) SIMDJSON_CAT(SIMDJSON_IMPLEMENTATION_ID_, IMPL)
|
||||
#define SIMDJSON_IMPLEMENTATION_ID SIMDJSON_IMPLEMENTATION_ID_FOR(SIMDJSON_IMPLEMENTATION)
|
||||
@@ -126,9 +128,14 @@
|
||||
#endif
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_LSX (SIMDJSON_IMPLEMENTATION_LSX)
|
||||
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS SIMDJSON_IS_RVV_VLS
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
#define SIMDJSON_IMPLEMENTATION_RVV_VLS SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS
|
||||
#endif
|
||||
|
||||
// Default Fallback to on unless a builtin implementation has already been selected.
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64 || SIMDJSON_CAN_ALWAYS_RUN_LSX || SIMDJSON_CAN_ALWAYS_RUN_LASX
|
||||
#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64 || SIMDJSON_CAN_ALWAYS_RUN_LSX || SIMDJSON_CAN_ALWAYS_RUN_LASX || SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS
|
||||
// if anything at all except fallback can always run, then disable fallback.
|
||||
#define SIMDJSON_IMPLEMENTATION_FALLBACK 0
|
||||
#else
|
||||
@@ -154,6 +161,8 @@
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION lsx
|
||||
#elif SIMDJSON_CAN_ALWAYS_RUN_LASX
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION lasx
|
||||
#elif SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION rvv_vls
|
||||
#elif SIMDJSON_CAN_ALWAYS_RUN_FALLBACK
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION fallback
|
||||
#else
|
||||
|
||||
@@ -69,6 +69,8 @@ enum instruction_set {
|
||||
AVX512VBMI2 = 0x10000,
|
||||
LSX = 0x20000,
|
||||
LASX = 0x40000,
|
||||
//RVV = 0x80000,
|
||||
RVV_VLS = 0x100000,
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -303,6 +303,7 @@ namespace simd {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 2, "LASX kernel should use two registers per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
|
||||
@@ -260,6 +260,7 @@ namespace simd {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 4, "LSX kernel should use four registers per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
|
||||
@@ -45,22 +45,20 @@ using std::size_t;
|
||||
#define SIMDJSON_IS_ARM64 1
|
||||
#elif defined(__riscv) && __riscv_xlen == 64
|
||||
#define SIMDJSON_IS_RISCV64 1
|
||||
|
||||
#if __riscv_v_intrinsic >= 11000
|
||||
#define SIMDJSON_HAS_RVV_INTRINSICS 1
|
||||
#endif
|
||||
|
||||
#define SIMDJSON_HAS_ZVBB_INTRINSICS \
|
||||
0 // there is currently no way to detect this
|
||||
|
||||
#if SIMDJSON_HAS_RVV_INTRINSICS && __riscv_vector && \
|
||||
__riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64
|
||||
// RISC-V V extension
|
||||
#define SIMDJSON_IS_RVV 1
|
||||
#if SIMDJSON_HAS_ZVBB_INTRINSICS && __riscv_zvbb >= 1000000
|
||||
// RISC-V Vector Basic Bit-manipulation
|
||||
#define SIMDJSON_IS_ZVBB 1
|
||||
#endif
|
||||
#if SIMDJSON_HAS_RVV_INTRINSICS && __riscv_vector && __riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64
|
||||
#define SIMDJSON_IS_RVV 1 // RISC-V V extension
|
||||
#endif
|
||||
|
||||
// current toolchains don't support fixed-size SIMD types that don't match VLEN directly
|
||||
#if __riscv_v_fixed_vlen >= 128 && __riscv_v_fixed_vlen <= 512
|
||||
#define SIMDJSON_IS_RVV_VLS 1
|
||||
#endif
|
||||
|
||||
#elif defined(__loongarch_lp64)
|
||||
#define SIMDJSON_IS_LOONGARCH64 1
|
||||
#if defined(__loongarch_sx) && defined(__loongarch_asx)
|
||||
|
||||
@@ -397,6 +397,7 @@ template <typename T> struct simd8x64 {
|
||||
static_assert(NUM_CHUNKS == 4,
|
||||
"PPC64 kernel should use four registers per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T> &o) = delete; // no copy allowed
|
||||
simd8x64<T> &
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_H
|
||||
#define SIMDJSON_RVV_VLS_H
|
||||
|
||||
|
||||
#include "simdjson/rvv-vls/begin.h"
|
||||
#include "simdjson/generic/amalgamated.h"
|
||||
#include "simdjson/rvv-vls/end.h"
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_H
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_BASE_H
|
||||
#define SIMDJSON_RVV_VLS_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
/**
|
||||
* RVV-VLS implementation.
|
||||
*/
|
||||
namespace rvv_vls {
|
||||
|
||||
class implementation;
|
||||
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_BASE_H
|
||||
@@ -0,0 +1,10 @@
|
||||
#define SIMDJSON_IMPLEMENTATION rvv_vls
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#include "simdjson/rvv-vls/intrinsics.h"
|
||||
#include "simdjson/rvv-vls/bitmanipulation.h"
|
||||
#include "simdjson/rvv-vls/bitmask.h"
|
||||
#include "simdjson/rvv-vls/simd.h"
|
||||
#include "simdjson/rvv-vls/stringparsing_defs.h"
|
||||
#include "simdjson/rvv-vls/numberparsing_defs.h"
|
||||
|
||||
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_BITMANIPULATION_H
|
||||
#define SIMDJSON_RVV_VLS_BITMANIPULATION_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
namespace {
|
||||
|
||||
// We sometimes call trailing_zero on inputs that are zero,
|
||||
// but the algorithms do not end up using the returned value.
|
||||
// Sadly, sanitizers are not smart enough to figure it out.
|
||||
SIMDJSON_NO_SANITIZE_UNDEFINED
|
||||
// This function can be used safely even if not all bytes have been
|
||||
// initialized.
|
||||
// See issue https://github.com/simdjson/simdjson/issues/1965
|
||||
SIMDJSON_NO_SANITIZE_MEMORY
|
||||
simdjson_inline int trailing_zeroes(uint64_t input_num) {
|
||||
return __builtin_ctzll(input_num);
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||
return input_num & (input_num-1);
|
||||
}
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
return __builtin_clzll(input_num);
|
||||
}
|
||||
|
||||
simdjson_inline long long int count_ones(uint64_t input_num) {
|
||||
return __builtin_popcountll(input_num);
|
||||
}
|
||||
|
||||
simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
||||
uint64_t *result) {
|
||||
return __builtin_uaddll_overflow(value1, value2,
|
||||
reinterpret_cast<unsigned long long *>(result));
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_BITMANIPULATION_H
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_BITMASK_H
|
||||
#define SIMDJSON_RVV_VLS_BITMASK_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#include "simdjson/rvv-vls/intrinsics.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered.
|
||||
//
|
||||
// For example, prefix_xor(00100100) == 00011100
|
||||
//
|
||||
simdjson_inline uint64_t prefix_xor(uint64_t bitmask) {
|
||||
#if __riscv_zbc
|
||||
return __riscv_clmul_64(bitmask, ~(uint64_t)0);
|
||||
#elif __riscv_zvbc
|
||||
return __riscv_vmv_x(__riscv_vclmul(__riscv_vmv_s_x_u64m1(bitmask, 1), ~(uint64_t)0, 1));
|
||||
#else
|
||||
bitmask ^= bitmask << 1;
|
||||
bitmask ^= bitmask << 2;
|
||||
bitmask ^= bitmask << 4;
|
||||
bitmask ^= bitmask << 8;
|
||||
bitmask ^= bitmask << 16;
|
||||
bitmask ^= bitmask << 32;
|
||||
#endif
|
||||
return bitmask;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_BITMASK_H
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_BUILDER_H
|
||||
#define SIMDJSON_RVV_VLS_BUILDER_H
|
||||
|
||||
#include "simdjson/rvv-vls/begin.h"
|
||||
#include "simdjson/generic/builder/amalgamated.h"
|
||||
#include "simdjson/rvv-vls/end.h"
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_BUILDER_H
|
||||
@@ -0,0 +1,5 @@
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#undef SIMDJSON_IMPLEMENTATION
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_IMPLEMENTATION_H
|
||||
#define SIMDJSON_RVV_VLS_IMPLEMENTATION_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#include "simdjson/implementation.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
class implementation final : public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation(
|
||||
"rvv_vls",
|
||||
"RISC-V V extension",
|
||||
0
|
||||
) {}
|
||||
simdjson_warn_unused error_code create_dom_parser_implementation(
|
||||
size_t capacity,
|
||||
size_t max_length,
|
||||
std::unique_ptr<simdjson::internal::dom_parser_implementation>& dst
|
||||
) const noexcept final;
|
||||
simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final;
|
||||
simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final;
|
||||
};
|
||||
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_IMPLEMENTATION_H
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_INTRINSICS_H
|
||||
#define SIMDJSON_RVV_VLS_INTRINSICS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
#define simdutf_vrgather_u8m1x2(tbl, idx) \
|
||||
__riscv_vcreate_v_u8m1_u8m2( \
|
||||
__riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m2_u8m1(idx, 0), \
|
||||
__riscv_vsetvlmax_e8m1()), \
|
||||
__riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m2_u8m1(idx, 1), \
|
||||
__riscv_vsetvlmax_e8m1()))
|
||||
|
||||
#define simdutf_vrgather_u8m1x4(tbl, idx) \
|
||||
__riscv_vcreate_v_u8m1_u8m4( \
|
||||
__riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 0), \
|
||||
__riscv_vsetvlmax_e8m1()), \
|
||||
__riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 1), \
|
||||
__riscv_vsetvlmax_e8m1()), \
|
||||
__riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 2), \
|
||||
__riscv_vsetvlmax_e8m1()), \
|
||||
__riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 3), \
|
||||
__riscv_vsetvlmax_e8m1()))
|
||||
|
||||
#if __riscv_zbc
|
||||
#include <riscv_bitmanip.h>
|
||||
#endif
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_INTRINSICS_H
|
||||
@@ -0,0 +1,56 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_NUMBERPARSING_DEFS_H
|
||||
#define SIMDJSON_RVV_VLS_NUMBERPARSING_DEFS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#include "simdjson/internal/numberparsing_tables.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef JSON_TEST_NUMBERS // for unit testing
|
||||
void found_invalid_number(const uint8_t *buf);
|
||||
void found_integer(int64_t result, const uint8_t *buf);
|
||||
void found_unsigned_integer(uint64_t result, const uint8_t *buf);
|
||||
void found_float(double result, const uint8_t *buf);
|
||||
#endif
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
namespace numberparsing {
|
||||
|
||||
// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
|
||||
/** @private */
|
||||
static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) {
|
||||
uint64_t val;
|
||||
#if __riscv_misaligned_fast
|
||||
memcpy(&val, chars, sizeof(uint64_t));
|
||||
#else
|
||||
val = __riscv_vmv_x(__riscv_vreinterpret_u64m1(__riscv_vlmul_ext_u8m1(__riscv_vle8_v_u8mf2((uint8_t*)chars, 8))));
|
||||
#endif
|
||||
val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8;
|
||||
val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16;
|
||||
return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32);
|
||||
}
|
||||
|
||||
/** @private */
|
||||
static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) {
|
||||
return parse_eight_digits_unrolled(reinterpret_cast<const char *>(chars));
|
||||
}
|
||||
|
||||
/** @private */
|
||||
simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
||||
internal::value128 answer;
|
||||
__uint128_t r = (static_cast<__uint128_t>(value1)) * value2;
|
||||
answer.low = uint64_t(r);
|
||||
answer.high = uint64_t(r >> 64);
|
||||
return answer;
|
||||
}
|
||||
|
||||
} // namespace numberparsing
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#define SIMDJSON_SWAR_NUMBER_PARSING 1
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_NUMBERPARSING_DEFS_H
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_ONDEMAND_H
|
||||
#define SIMDJSON_RVV_VLS_ONDEMAND_H
|
||||
|
||||
#include "simdjson/rvv-vls/begin.h"
|
||||
#include "simdjson/generic/ondemand/amalgamated.h"
|
||||
#include "simdjson/rvv-vls/end.h"
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_ONDEMAND_H
|
||||
@@ -0,0 +1,370 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_SIMD_H
|
||||
#define SIMDJSON_RVV_VLS_SIMD_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#include "simdjson/rvv-vls/bitmanipulation.h"
|
||||
#include "simdjson/internal/simdprune_tables.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
namespace {
|
||||
namespace simd {
|
||||
|
||||
#if __riscv_v_fixed_vlen >= 512
|
||||
static constexpr size_t VL8 = 512/8;
|
||||
using vint8_t = vint8m1_t __attribute__((riscv_rvv_vector_bits(512)));
|
||||
using vuint8_t = vuint8m1_t __attribute__((riscv_rvv_vector_bits(512)));
|
||||
using vbool_t = vbool8_t __attribute__((riscv_rvv_vector_bits(512/8)));
|
||||
using vbitmask_t = uint64_t;
|
||||
#else
|
||||
static constexpr size_t VL8 = __riscv_v_fixed_vlen/8;
|
||||
using vint8_t = vint8m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
|
||||
using vuint8_t = vuint8m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen)));
|
||||
using vbool_t = vbool8_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen/8)));
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
using vbitmask_t = uint16_t;
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
using vbitmask_t = uint32_t;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
using vuint8x64_t = vuint8m4_t __attribute__((riscv_rvv_vector_bits(512)));
|
||||
using vboolx64_t = vbool2_t __attribute__((riscv_rvv_vector_bits(512/8)));
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
using vuint8x64_t = vuint8m2_t __attribute__((riscv_rvv_vector_bits(512)));
|
||||
using vboolx64_t = vbool4_t __attribute__((riscv_rvv_vector_bits(512/8)));
|
||||
#else
|
||||
using vuint8x64_t = vuint8m1_t __attribute__((riscv_rvv_vector_bits(512)));
|
||||
using vboolx64_t = vbool8_t __attribute__((riscv_rvv_vector_bits(512/8)));
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
struct simd8;
|
||||
|
||||
// SIMD byte mask type (returned by things like eq and gt)
|
||||
template<>
|
||||
struct simd8<bool> {
|
||||
vbool_t value;
|
||||
using bitmask_t = vbitmask_t;
|
||||
static constexpr int SIZE = sizeof(value);
|
||||
|
||||
simdjson_inline simd8(const vbool_t _value) : value(_value) {}
|
||||
simdjson_inline simd8() : simd8(__riscv_vmclr_m_b8(VL8)) {}
|
||||
simdjson_inline simd8(bool _value) : simd8(splat(_value)) {}
|
||||
|
||||
simdjson_inline operator const vbool_t&() const { return value; }
|
||||
simdjson_inline operator vbool_t&() { return value; }
|
||||
|
||||
static simdjson_inline simd8<bool> splat(bool _value) {
|
||||
return __riscv_vreinterpret_b8(__riscv_vmv_v_x_u64m1(((uint64_t)!_value)-1, 1));
|
||||
}
|
||||
|
||||
simdjson_inline vbitmask_t to_bitmask() const {
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
return __riscv_vmv_x(__riscv_vreinterpret_u16m1(value));
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
return __riscv_vmv_x(__riscv_vreinterpret_u32m1(value));
|
||||
#else
|
||||
return __riscv_vmv_x(__riscv_vreinterpret_u64m1(value));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Bit operations
|
||||
simdjson_inline simd8<bool> operator|(const simd8<bool> other) const { return __riscv_vmor(*this, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator&(const simd8<bool> other) const { return __riscv_vmand(*this, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator^(const simd8<bool> other) const { return __riscv_vmxor(*this, other, VL8); }
|
||||
simdjson_inline simd8<bool> bit_andnot(const simd8<bool> other) const { return __riscv_vmandn(other, *this, VL8); }
|
||||
simdjson_inline simd8<bool> operator~() const { return __riscv_vmnot(*this, VL8); }
|
||||
simdjson_inline simd8<bool>& operator|=(const simd8<bool> other) { auto this_cast = static_cast<simd8<bool>*>(this); *this_cast = *this_cast | other; return *this_cast; }
|
||||
simdjson_inline simd8<bool>& operator&=(const simd8<bool> other) { auto this_cast = static_cast<simd8<bool>*>(this); *this_cast = *this_cast & other; return *this_cast; }
|
||||
simdjson_inline simd8<bool>& operator^=(const simd8<bool> other) { auto this_cast = static_cast<simd8<bool>*>(this); *this_cast = *this_cast ^ other; return *this_cast; }
|
||||
};
|
||||
|
||||
// Unsigned bytes
|
||||
template<>
|
||||
struct simd8<uint8_t> {
|
||||
|
||||
vuint8_t value;
|
||||
static constexpr int SIZE = sizeof(value);
|
||||
|
||||
simdjson_inline simd8(const vuint8_t _value) : value(_value) {}
|
||||
simdjson_inline simd8() : simd8(zero()) {}
|
||||
simdjson_inline simd8(const uint8_t values[VL8]) : simd8(load(values)) {}
|
||||
simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {}
|
||||
simdjson_inline simd8(simd8<bool> mask) : value(__riscv_vmerge_vxm_u8m1(zero(), -1, (vbool_t)mask, VL8)) {}
|
||||
|
||||
simdjson_inline operator const vuint8_t&() const { return this->value; }
|
||||
simdjson_inline operator vuint8_t&() { return this->value; }
|
||||
|
||||
simdjson_inline simd8(
|
||||
uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
|
||||
uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
|
||||
) : simd8(vuint8_t{
|
||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||
v8, v9, v10,v11,v12,v13,v14,v15
|
||||
}) {}
|
||||
|
||||
// Repeat 16 values as many times as necessary (usually for lookup tables)
|
||||
simdjson_inline static simd8<uint8_t> repeat_16(
|
||||
uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7,
|
||||
uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15
|
||||
) {
|
||||
return simd8<uint8_t>(
|
||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||
v8, v9, v10,v11,v12,v13,v14,v15
|
||||
);
|
||||
}
|
||||
|
||||
static simdjson_inline vuint8_t splat(uint8_t _value) { return __riscv_vmv_v_x_u8m1(_value, VL8); }
|
||||
static simdjson_inline vuint8_t zero() { return splat(0); }
|
||||
static simdjson_inline vuint8_t load(const uint8_t values[VL8]) { return __riscv_vle8_v_u8m1(values, VL8); }
|
||||
|
||||
// Bit operations
|
||||
simdjson_inline simd8<uint8_t> operator|(const simd8<uint8_t> other) const { return __riscv_vor_vv_u8m1( value, other, VL8); }
|
||||
simdjson_inline simd8<uint8_t> operator&(const simd8<uint8_t> other) const { return __riscv_vand_vv_u8m1( value, other, VL8); }
|
||||
simdjson_inline simd8<uint8_t> operator^(const simd8<uint8_t> other) const { return __riscv_vxor_vv_u8m1( value, other, VL8); }
|
||||
simdjson_inline simd8<uint8_t> operator~() const { return __riscv_vnot_v_u8m1(value, VL8); }
|
||||
#if __riscv_zvbb
|
||||
simdjson_inline simd8<uint8_t> bit_andnot(const simd8<uint8_t> other) const { return __riscv_vandn_vv_u8m1(other, value, VL8); }
|
||||
#else
|
||||
simdjson_inline simd8<uint8_t> bit_andnot(const simd8<uint8_t> other) const { return other & ~*this; }
|
||||
#endif
|
||||
simdjson_inline simd8<uint8_t>& operator|=(const simd8<uint8_t> other) { value = *this | other; return *this; }
|
||||
simdjson_inline simd8<uint8_t>& operator&=(const simd8<uint8_t> other) { value = *this & other; return *this; }
|
||||
simdjson_inline simd8<uint8_t>& operator^=(const simd8<uint8_t> other) { value = *this ^ other; return *this; }
|
||||
|
||||
simdjson_inline simd8<bool> operator==(const simd8<uint8_t> other) const { return __riscv_vmseq(value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator==(uint8_t other) const { return __riscv_vmseq(value, other, VL8); }
|
||||
|
||||
template<int N=1>
|
||||
simdjson_inline simd8<uint8_t> prev(const simd8<uint8_t> prev_chunk) const {
|
||||
return __riscv_vslideup(__riscv_vslidedown(prev_chunk, VL8-N, VL8), value, N, VL8);
|
||||
}
|
||||
|
||||
// Store to array
|
||||
simdjson_inline void store(uint8_t dst[VL8]) const { return __riscv_vse8(dst, value, VL8); }
|
||||
|
||||
// Saturated math
|
||||
simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> other) const { return __riscv_vsaddu(value, other, VL8); }
|
||||
simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> other) const { return __riscv_vssubu(value, other, VL8); }
|
||||
|
||||
// Addition/subtraction are the same for signed and unsigned
|
||||
simdjson_inline simd8<uint8_t> operator+(const simd8<uint8_t> other) const { return __riscv_vadd(value, other, VL8); }
|
||||
simdjson_inline simd8<uint8_t> operator-(const simd8<uint8_t> other) const { return __riscv_vsub(value, other, VL8); }
|
||||
simdjson_inline simd8<uint8_t>& operator+=(const simd8<uint8_t> other) { value = *this + other; return *this; }
|
||||
simdjson_inline simd8<uint8_t>& operator-=(const simd8<uint8_t> other) { value = *this - other; return *this; }
|
||||
|
||||
// Order-specific operations
|
||||
simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> other) const { return __riscv_vmsleu(value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> other) const { return __riscv_vmsgeu(value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator<(const simd8<uint8_t> other) const { return __riscv_vmsltu(value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator>(const simd8<uint8_t> other) const { return __riscv_vmsgtu(value, other, VL8); }
|
||||
|
||||
// Same as >, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero.
|
||||
simdjson_inline simd8<uint8_t> gt_bits(const simd8<uint8_t> other) const { return simd8<uint8_t>(*this > other); }
|
||||
// Same as <, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero.
|
||||
simdjson_inline simd8<uint8_t> lt_bits(const simd8<uint8_t> other) const { return simd8<uint8_t>(*this < other); }
|
||||
|
||||
// Bit-specific operations
|
||||
simdjson_inline bool any_bits_set_anywhere() const {
|
||||
return __riscv_vfirst(__riscv_vmsne(value, 0, VL8), VL8) >= 0;
|
||||
}
|
||||
simdjson_inline bool any_bits_set_anywhere(simd8<uint8_t> bits) const { return (*this & bits).any_bits_set_anywhere(); }
|
||||
template<int N>
|
||||
simdjson_inline simd8<uint8_t> shr() const { return __riscv_vsrl(value, N, VL8); }
|
||||
template<int N>
|
||||
simdjson_inline simd8<uint8_t> shl() const { return __riscv_vsll(value, N, VL8); }
|
||||
|
||||
|
||||
// Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values)
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
|
||||
return __riscv_vrgather(lookup_table, value, VL8);
|
||||
}
|
||||
|
||||
// compress inactive elements, to match AVX-512 behavior
|
||||
template<typename L>
|
||||
simdjson_inline void compress(vbitmask_t mask, L * output) const {
|
||||
mask = (vbitmask_t)~mask;
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
vbool8_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u16m1(mask, 1));
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
vbool8_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u32m1(mask, 1));
|
||||
#else
|
||||
vbool8_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u64m1(mask, 1));
|
||||
#endif
|
||||
__riscv_vse8_v_u8m1(output, __riscv_vcompress(value, m, VL8), count_ones(mask));
|
||||
}
|
||||
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(
|
||||
L replace0, L replace1, L replace2, L replace3,
|
||||
L replace4, L replace5, L replace6, L replace7,
|
||||
L replace8, L replace9, L replace10, L replace11,
|
||||
L replace12, L replace13, L replace14, L replace15) const {
|
||||
return lookup_16(simd8<L>::repeat_16(
|
||||
replace0, replace1, replace2, replace3,
|
||||
replace4, replace5, replace6, replace7,
|
||||
replace8, replace9, replace10, replace11,
|
||||
replace12, replace13, replace14, replace15
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// Signed bytes
|
||||
template<>
|
||||
struct simd8<int8_t> {
|
||||
vint8_t value;
|
||||
static constexpr int SIZE = sizeof(value);
|
||||
|
||||
simdjson_inline simd8(const vint8_t _value) : value(_value) {}
|
||||
simdjson_inline simd8() : simd8(zero()) {}
|
||||
simdjson_inline simd8(const int8_t values[VL8]) : simd8(load(values)) {}
|
||||
simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {}
|
||||
|
||||
simdjson_inline operator const vint8_t&() const { return this->value; }
|
||||
simdjson_inline operator vint8_t&() { return this->value; }
|
||||
|
||||
simdjson_inline simd8(
|
||||
int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7,
|
||||
int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
|
||||
) : simd8(vint8_t{
|
||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||
v8, v9, v10,v11,v12,v13,v14,v15
|
||||
}) {}
|
||||
|
||||
// Repeat 16 values as many times as necessary (usually for lookup tables)
|
||||
simdjson_inline static simd8<int8_t> repeat_16(
|
||||
int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7,
|
||||
int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15
|
||||
) {
|
||||
return simd8<int8_t>(
|
||||
v0, v1, v2, v3, v4, v5, v6, v7,
|
||||
v8, v9, v10,v11,v12,v13,v14,v15
|
||||
);
|
||||
}
|
||||
|
||||
static simdjson_inline vint8_t splat(int8_t _value) { return __riscv_vmv_v_x_i8m1(_value, VL8); }
|
||||
static simdjson_inline vint8_t zero() { return splat(0); }
|
||||
static simdjson_inline vint8_t load(const int8_t values[VL8]) { return __riscv_vle8_v_i8m1(values, VL8); }
|
||||
|
||||
|
||||
simdjson_inline void store(int8_t dst[VL8]) const { return __riscv_vse8(dst, value, VL8); }
|
||||
|
||||
// Explicit conversion to/from unsigned
|
||||
simdjson_inline explicit simd8(const vuint8_t other): simd8(__riscv_vreinterpret_i8m1(other)) {}
|
||||
simdjson_inline explicit operator simd8<uint8_t>() const { return __riscv_vreinterpret_u8m1(value); }
|
||||
|
||||
// Math
|
||||
simdjson_inline simd8<int8_t> operator+(const simd8<int8_t> other) const { return __riscv_vadd(value, other, VL8); }
|
||||
simdjson_inline simd8<int8_t> operator-(const simd8<int8_t> other) const { return __riscv_vsub(value, other, VL8); }
|
||||
simdjson_inline simd8<int8_t>& operator+=(const simd8<int8_t> other) { value = *this + other; return *this; }
|
||||
simdjson_inline simd8<int8_t>& operator-=(const simd8<int8_t> other) { value = *this - other; return *this; }
|
||||
|
||||
// Order-sensitive comparisons
|
||||
simdjson_inline simd8<int8_t> max_val( const simd8<int8_t> other) const { return __riscv_vmax( value, other, VL8); }
|
||||
simdjson_inline simd8<int8_t> min_val( const simd8<int8_t> other) const { return __riscv_vmin( value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator>( const simd8<int8_t> other) const { return __riscv_vmsgt(value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator<( const simd8<int8_t> other) const { return __riscv_vmslt(value, other, VL8); }
|
||||
simdjson_inline simd8<bool> operator==(const simd8<int8_t> other) const { return __riscv_vmseq(value, other, VL8); }
|
||||
|
||||
template<int N=1>
|
||||
simdjson_inline simd8<int8_t> prev(const simd8<int8_t> prev_chunk) const {
|
||||
return __riscv_vslideup(__riscv_vslidedown(prev_chunk, VL8-N, VL8), value, N, VL8);
|
||||
}
|
||||
|
||||
// Perform a lookup assuming no value is larger than 16
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(simd8<L> lookup_table) const {
|
||||
return __riscv_vrgather(lookup_table, value, VL8);
|
||||
}
|
||||
template<typename L>
|
||||
simdjson_inline simd8<L> lookup_16(
|
||||
L replace0, L replace1, L replace2, L replace3,
|
||||
L replace4, L replace5, L replace6, L replace7,
|
||||
L replace8, L replace9, L replace10, L replace11,
|
||||
L replace12, L replace13, L replace14, L replace15) const {
|
||||
return lookup_16(simd8<L>::repeat_16(
|
||||
replace0, replace1, replace2, replace3,
|
||||
replace4, replace5, replace6, replace7,
|
||||
replace8, replace9, replace10, replace11,
|
||||
replace12, replace13, replace14, replace15
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct simd8x64;
|
||||
template<>
|
||||
struct simd8x64<uint8_t> {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<uint8_t>);
|
||||
vuint8x64_t value;
|
||||
|
||||
#if __riscv_v_fixed_vlen >= 512
|
||||
template<int idx> simd8<uint8_t> get() const { return value; }
|
||||
#else
|
||||
template<int idx> simd8<uint8_t> get() const { return __riscv_vget_u8m1(value, idx); }
|
||||
#endif
|
||||
|
||||
simdjson_inline operator const vuint8x64_t&() const { return this->value; }
|
||||
simdjson_inline operator vuint8x64_t&() { return this->value; }
|
||||
|
||||
simd8x64(const simd8x64<uint8_t>& o) = delete; // no copy allowed
|
||||
simd8x64<uint8_t>& operator=(const simd8<uint8_t>& other) = delete; // no assignment allowed
|
||||
simd8x64() = delete; // no default constructor allowed
|
||||
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
simdjson_inline simd8x64(const uint8_t *ptr, size_t n = 64) : value(__riscv_vle8_v_u8m4(ptr, n)) {}
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
simdjson_inline simd8x64(const uint8_t *ptr, size_t n = 64) : value(__riscv_vle8_v_u8m2(ptr, n)) {}
|
||||
#else
|
||||
simdjson_inline simd8x64(const uint8_t *ptr, size_t n = 64) : value(__riscv_vle8_v_u8m1(ptr, n)) {}
|
||||
#endif
|
||||
|
||||
simdjson_inline void store(uint8_t ptr[64]) const {
|
||||
__riscv_vse8(ptr, value, 64);
|
||||
}
|
||||
|
||||
simdjson_inline bool is_ascii() const {
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
return __riscv_vfirst(__riscv_vmslt(__riscv_vreinterpret_i8m4(value), 0, 64), 64) < 0;
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
return __riscv_vfirst(__riscv_vmslt(__riscv_vreinterpret_i8m2(value), 0, 64), 64) < 0;
|
||||
#else
|
||||
return __riscv_vfirst(__riscv_vmslt(__riscv_vreinterpret_i8m1(value), 0, 64), 64) < 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// compress inactive elements, to match AVX-512 behavior
|
||||
simdjson_inline uint64_t compress(uint64_t mask, uint8_t * output) const {
|
||||
mask = ~mask;
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
vboolx64_t m = __riscv_vreinterpret_b2(__riscv_vmv_s_x_u64m1(mask, 1));
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
vboolx64_t m = __riscv_vreinterpret_b4(__riscv_vmv_s_x_u64m1(mask, 1));
|
||||
#else
|
||||
vboolx64_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u64m1(mask, 1));
|
||||
#endif
|
||||
size_t cnt = count_ones(mask);
|
||||
__riscv_vse8(output, __riscv_vcompress(value, m, 64), cnt);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
simdjson_inline uint64_t eq(const uint8_t m) const {
|
||||
return __riscv_vmv_x(__riscv_vreinterpret_u64m1(__riscv_vmseq(value, m, 64)));
|
||||
}
|
||||
|
||||
simdjson_inline uint64_t lteq(const uint8_t m) const {
|
||||
return __riscv_vmv_x(__riscv_vreinterpret_u64m1(__riscv_vmsleu(value, m, 64)));
|
||||
}
|
||||
}; // struct simd8x64<uint8_t>
|
||||
|
||||
} // namespace simd
|
||||
} // unnamed namespace
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_SIMD_H
|
||||
@@ -0,0 +1,58 @@
|
||||
#ifndef SIMDJSON_RVV_VLS_STRINGPARSING_DEFS_H
|
||||
#define SIMDJSON_RVV_VLS_STRINGPARSING_DEFS_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv-vls/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
namespace {
|
||||
|
||||
using namespace simd;
|
||||
|
||||
// Holds backslashes and quotes locations.
|
||||
struct backslash_and_quote {
|
||||
public:
|
||||
static constexpr uint64_t BYTES_PROCESSED = sizeof(simd8<uint8_t>);
|
||||
simdjson_inline backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst);
|
||||
|
||||
simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; }
|
||||
simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; }
|
||||
simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); }
|
||||
simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); }
|
||||
|
||||
uint64_t bs_bits;
|
||||
uint64_t quote_bits;
|
||||
}; // struct backslash_and_quote
|
||||
|
||||
simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) {
|
||||
static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes");
|
||||
simd8<uint8_t> v(src);
|
||||
v.store(dst);
|
||||
return { (v == '\\').to_bitmask(), (v == '"').to_bitmask() };
|
||||
}
|
||||
|
||||
struct escaping {
|
||||
static constexpr uint64_t BYTES_PROCESSED = sizeof(simd8<uint8_t>);
|
||||
simdjson_inline static escaping copy_and_find(const uint8_t *src, uint8_t *dst);
|
||||
|
||||
simdjson_inline bool has_escape() { return escape_bits != 0; }
|
||||
simdjson_inline int escape_index() { return trailing_zeroes(escape_bits) / 4; }
|
||||
|
||||
uint64_t escape_bits;
|
||||
}; // struct escaping
|
||||
|
||||
simdjson_inline escaping escaping::copy_and_find(const uint8_t *src, uint8_t *dst) {
|
||||
static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "escaping finder must process fewer than SIMDJSON_PADDING bytes");
|
||||
simd8<uint8_t> v(src);
|
||||
v.store(dst);
|
||||
return { ((v == '"') | (v == '\\') | (v == 32)).to_bitmask() };
|
||||
}
|
||||
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_VLS_STRINGPARSING_DEFS_H
|
||||
@@ -265,6 +265,7 @@ namespace simd {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 4, "Westmere kernel should use four registers per 64-byte block.");
|
||||
const simd8<T> chunks[NUM_CHUNKS];
|
||||
template<int idx> simd8<uint8_t> get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8<T>(); }
|
||||
|
||||
simd8x64(const simd8x64<T>& o) = delete; // no copy allowed
|
||||
simd8x64<T>& operator=(const simd8<T>& other) = delete; // no assignment allowed
|
||||
|
||||
@@ -108,7 +108,7 @@ else:
|
||||
RelativeRoot = str # Literal['src','include'] # Literal not supported in Python 3.7 (CI)
|
||||
RELATIVE_ROOTS: List[RelativeRoot] = ['src', 'include' ]
|
||||
Implementation = str # Literal['arm64', 'fallback', 'haswell', 'icelake', 'ppc64', 'westmere', 'lsx', 'lasx'] # Literal not supported in Python 3.7 (CI)
|
||||
IMPLEMENTATIONS: List[Implementation] = [ 'arm64', 'haswell', 'icelake', 'lasx', 'lsx', 'ppc64', 'westmere', 'fallback' ]
|
||||
IMPLEMENTATIONS: List[Implementation] = [ 'arm64', 'haswell', 'icelake', 'lasx', 'lsx', 'ppc64', 'rvv-vls', 'westmere', 'fallback' ]
|
||||
GENERIC_INCLUDE = "simdjson/generic"
|
||||
GENERIC_SRC = "generic"
|
||||
BUILTIN = "simdjson/builtin"
|
||||
|
||||
@@ -18,4 +18,4 @@ simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input);
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_SRC_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||
#endif // SIMDJSON_SRC_GENERIC_DOM_PARSER_IMPLEMENTATION_H
|
||||
|
||||
@@ -119,7 +119,7 @@ using namespace simd;
|
||||
simdjson_inline simd8<uint8_t> is_incomplete(const simd8<uint8_t> input) {
|
||||
// If the previous input's last 3 bytes match this, they're too short (they ended at EOF):
|
||||
// ... 1111____ 111_____ 11______
|
||||
#if SIMDJSON_IMPLEMENTATION_ICELAKE
|
||||
#if SIMDJSON_IMPLEMENTATION_ICELAKE || (SIMDJSON_IMPLEMENTATION_RVV_VLS && __riscv_v_fixed_vlen >= 512)
|
||||
static const uint8_t max_array[64] = {
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
@@ -180,18 +180,18 @@ using namespace simd;
|
||||
|| (simd8x64<uint8_t>::NUM_CHUNKS == 4),
|
||||
"We support one, two or four chunks per 64-byte block.");
|
||||
SIMDJSON_IF_CONSTEXPR (simd8x64<uint8_t>::NUM_CHUNKS == 1) {
|
||||
this->check_utf8_bytes(input.chunks[0], this->prev_input_block);
|
||||
this->check_utf8_bytes(input.get<0>(), this->prev_input_block);
|
||||
} else SIMDJSON_IF_CONSTEXPR (simd8x64<uint8_t>::NUM_CHUNKS == 2) {
|
||||
this->check_utf8_bytes(input.chunks[0], this->prev_input_block);
|
||||
this->check_utf8_bytes(input.chunks[1], input.chunks[0]);
|
||||
this->check_utf8_bytes(input.get<0>(), this->prev_input_block);
|
||||
this->check_utf8_bytes(input.get<1>(), input.get<0>());
|
||||
} else SIMDJSON_IF_CONSTEXPR (simd8x64<uint8_t>::NUM_CHUNKS == 4) {
|
||||
this->check_utf8_bytes(input.chunks[0], this->prev_input_block);
|
||||
this->check_utf8_bytes(input.chunks[1], input.chunks[0]);
|
||||
this->check_utf8_bytes(input.chunks[2], input.chunks[1]);
|
||||
this->check_utf8_bytes(input.chunks[3], input.chunks[2]);
|
||||
this->check_utf8_bytes(input.get<0>(), this->prev_input_block);
|
||||
this->check_utf8_bytes(input.get<1>(), input.get<0>());
|
||||
this->check_utf8_bytes(input.get<2>(), input.get<1>());
|
||||
this->check_utf8_bytes(input.get<3>(), input.get<2>());
|
||||
}
|
||||
this->prev_incomplete = is_incomplete(input.chunks[simd8x64<uint8_t>::NUM_CHUNKS-1]);
|
||||
this->prev_input_block = input.chunks[simd8x64<uint8_t>::NUM_CHUNKS-1];
|
||||
this->prev_incomplete = is_incomplete(input.get<simd8x64<uint8_t>::NUM_CHUNKS-1>());
|
||||
this->prev_input_block = input.get<simd8x64<uint8_t>::NUM_CHUNKS-1>();
|
||||
}
|
||||
}
|
||||
// do not forget to call check_eof!
|
||||
@@ -206,4 +206,4 @@ using namespace simd;
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_SRC_GENERIC_STAGE1_UTF8_LOOKUP4_ALGORITHM_H
|
||||
#endif // SIMDJSON_SRC_GENERIC_STAGE1_UTF8_LOOKUP4_ALGORITHM_H
|
||||
|
||||
+18
-1
@@ -118,6 +118,17 @@ static const simdjson::lsx::implementation* get_lsx_singleton() {
|
||||
} // namespace simdjson
|
||||
#endif // SIMDJSON_IMPLEMENTATION_LSX
|
||||
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
#include <simdjson/rvv-vls/implementation.h>
|
||||
namespace simdjson {
|
||||
namespace internal {
|
||||
static const simdjson::rvv_vls::implementation* get_rvv_vls_singleton() {
|
||||
static const simdjson::rvv_vls::implementation rvv_vls_singleton{};
|
||||
return &rvv_vls_singleton;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace simdjson
|
||||
#endif // SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
|
||||
#undef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
@@ -131,7 +142,7 @@ namespace internal {
|
||||
+ SIMDJSON_IMPLEMENTATION_HASWELL + SIMDJSON_IMPLEMENTATION_WESTMERE \
|
||||
+ SIMDJSON_IMPLEMENTATION_ARM64 + SIMDJSON_IMPLEMENTATION_PPC64 \
|
||||
+ SIMDJSON_IMPLEMENTATION_LSX + SIMDJSON_IMPLEMENTATION_LASX \
|
||||
+ SIMDJSON_IMPLEMENTATION_FALLBACK == 1)
|
||||
+ SIMDJSON_IMPLEMENTATION_RVV_VLS + SIMDJSON_IMPLEMENTATION_FALLBACK == 1)
|
||||
|
||||
#if SIMDJSON_SINGLE_IMPLEMENTATION
|
||||
static const implementation* get_single_implementation() {
|
||||
@@ -157,6 +168,9 @@ namespace internal {
|
||||
#if SIMDJSON_IMPLEMENTATION_LASX
|
||||
get_lasx_singleton();
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
get_rvv_vls_singleton();
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
get_fallback_singleton();
|
||||
#endif
|
||||
@@ -217,6 +231,9 @@ static const std::initializer_list<const implementation *>& get_available_implem
|
||||
#if SIMDJSON_IMPLEMENTATION_LSX
|
||||
get_lsx_singleton(),
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
get_rvv_vls_singleton(),
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
get_fallback_singleton(),
|
||||
#endif
|
||||
|
||||
@@ -239,6 +239,16 @@ static inline uint32_t detect_supported_architectures() {
|
||||
return host_isa;
|
||||
}
|
||||
|
||||
#elif SIMDJSON_IS_RISCV64
|
||||
|
||||
static inline uint32_t detect_supported_architectures() {
|
||||
uint32_t host_isa = instruction_set::DEFAULT;
|
||||
#if SIMDJSON_IS_RVV_VLS
|
||||
host_isa |= instruction_set::RVV_VLS;
|
||||
#endif
|
||||
return host_isa;
|
||||
}
|
||||
|
||||
#else // fallback
|
||||
|
||||
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
#ifndef SIMDJSON_SRC_RVV_VLS_CPP
|
||||
#define SIMDJSON_SRC_RVV_VLS_CPP
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include <base.h>
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#include <simdjson/rvv-vls.h>
|
||||
#include <simdjson/rvv-vls/implementation.h>
|
||||
|
||||
#include <simdjson/rvv-vls/begin.h>
|
||||
#include <simdjson/rvv-vls/simd.h>
|
||||
#include <generic/amalgamated.h>
|
||||
#include <generic/stage1/amalgamated.h>
|
||||
#include <generic/stage2/amalgamated.h>
|
||||
|
||||
//
|
||||
// Stage 1
|
||||
//
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
|
||||
simdjson_warn_unused error_code implementation::create_dom_parser_implementation(
|
||||
size_t capacity,
|
||||
size_t max_depth,
|
||||
std::unique_ptr<internal::dom_parser_implementation>& dst
|
||||
) const noexcept {
|
||||
dst.reset( new (std::nothrow) dom_parser_implementation() );
|
||||
if (!dst) { return MEMALLOC; }
|
||||
if (auto err = dst->set_capacity(capacity))
|
||||
return err;
|
||||
if (auto err = dst->set_max_depth(max_depth))
|
||||
return err;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace simd;
|
||||
|
||||
simdjson_inline json_character_block json_character_block::classify(const simd::simd8x64<uint8_t>& in) {
|
||||
static const uint8_t wsTable[16] = { ' ', 100, 100, 100, 17, 100, 113, 2, 100, '\t', '\n', 112, 100, '\r', 100, 100 };
|
||||
static const uint8_t opTable[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ':', '{', ',', '}', 0, 0 };
|
||||
vuint8_t vws = __riscv_vle8_v_u8m1(wsTable, 16);
|
||||
vuint8_t vop = __riscv_vle8_v_u8m1(opTable, 16);
|
||||
vuint8x64_t lo = __riscv_vand(in, 15, 64);
|
||||
vuint8x64_t curl = __riscv_vor(in, 0x20, 64);
|
||||
|
||||
#if __riscv_v_fixed_vlen == 128
|
||||
vboolx64_t mws = __riscv_vmseq(simdutf_vrgather_u8m1x4(vws, lo), in, 64);
|
||||
vboolx64_t mop = __riscv_vmseq(simdutf_vrgather_u8m1x4(vop, lo), curl, 64);
|
||||
#elif __riscv_v_fixed_vlen == 256
|
||||
vboolx64_t mws = __riscv_vmseq(simdutf_vrgather_u8m1x2(vws, lo), in, 64);
|
||||
vboolx64_t mop = __riscv_vmseq(simdutf_vrgather_u8m1x2(vop, lo), curl, 64);
|
||||
#else
|
||||
vboolx64_t mws = __riscv_vmseq(__riscv_vrgather(vws, lo, 64), in, 64);
|
||||
vboolx64_t mop = __riscv_vmseq(__riscv_vrgather(vop, lo, 64), curl, 64);
|
||||
#endif
|
||||
|
||||
return {
|
||||
__riscv_vmv_x(__riscv_vreinterpret_u64m1(mws)),
|
||||
__riscv_vmv_x(__riscv_vreinterpret_u64m1(mop))
|
||||
};
|
||||
}
|
||||
|
||||
simdjson_inline bool is_ascii(const simd8x64<uint8_t>& input) {
|
||||
return input.is_ascii();
|
||||
}
|
||||
|
||||
simdjson_inline simd8<uint8_t> must_be_2_3_continuation(const simd8<uint8_t> prev2, const simd8<uint8_t> prev3) {
|
||||
simd8<uint8_t> is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80
|
||||
simd8<uint8_t> is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80
|
||||
return is_third_byte | is_fourth_byte;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
//
|
||||
// Stage 2
|
||||
//
|
||||
|
||||
//
|
||||
// Implementation-specific overrides
|
||||
//
|
||||
namespace simdjson {
|
||||
namespace rvv_vls {
|
||||
|
||||
simdjson_warn_unused error_code implementation::minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept {
|
||||
return rvv_vls::stage1::json_minifier::minify<64>(buf, len, dst, dst_len);
|
||||
}
|
||||
|
||||
simdjson_warn_unused error_code dom_parser_implementation::stage1(const uint8_t *_buf, size_t _len, stage1_mode streaming) noexcept {
|
||||
this->buf = _buf;
|
||||
this->len = _len;
|
||||
return rvv_vls::stage1::json_structural_indexer::index<64>(buf, len, *this, streaming);
|
||||
}
|
||||
|
||||
simdjson_warn_unused bool implementation::validate_utf8(const char *buf, size_t len) const noexcept {
|
||||
return rvv_vls::stage1::generic_validate_utf8(buf,len);
|
||||
}
|
||||
|
||||
simdjson_warn_unused error_code dom_parser_implementation::stage2(dom::document &_doc) noexcept {
|
||||
return stage2::tape_builder::parse_document<false>(*this, _doc);
|
||||
}
|
||||
|
||||
simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::document &_doc) noexcept {
|
||||
return stage2::tape_builder::parse_document<true>(*this, _doc);
|
||||
}
|
||||
|
||||
SIMDJSON_NO_SANITIZE_MEMORY
|
||||
simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept {
|
||||
return rvv_vls::stringparsing::parse_string(src, dst, allow_replacement);
|
||||
}
|
||||
|
||||
simdjson_warn_unused uint8_t *dom_parser_implementation::parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept {
|
||||
return rvv_vls::stringparsing::parse_wobbly_string(src, dst);
|
||||
}
|
||||
|
||||
simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept {
|
||||
auto error = stage1(_buf, _len, stage1_mode::regular);
|
||||
if (error) { return error; }
|
||||
return stage2(_doc);
|
||||
}
|
||||
|
||||
} // namespace rvv_vls
|
||||
} // namespace simdjson
|
||||
|
||||
#include <simdjson/rvv-vls/end.h>
|
||||
|
||||
#endif // SIMDJSON_SRC_RVV_VLS_CPP
|
||||
@@ -41,6 +41,9 @@ SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
|
||||
#if SIMDJSON_IMPLEMENTATION_LSX
|
||||
#include <lsx.cpp>
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV_VLS
|
||||
#include <rvv-vls.cpp>
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
#include <fallback.cpp>
|
||||
#endif
|
||||
|
||||
@@ -79,7 +79,7 @@ if (BASH AND (NOT WIN32) AND SIMDJSON_BASH AND (TARGET json2json)) # The scripts
|
||||
$<TARGET_FILE:checkimplementation>
|
||||
)
|
||||
endif()
|
||||
if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL amd64)
|
||||
if((CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL amd64) AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR)
|
||||
add_test(
|
||||
NAME simdjson_force_implementation_error
|
||||
COMMAND
|
||||
|
||||
Reference in New Issue
Block a user