mirror of
https://github.com/simdjson/simdjson
synced 2026-06-08 17:27:07 +00:00
Compare commits
5 Commits
v4.3.1
...
riscv_develop
| Author | SHA1 | Date | |
|---|---|---|---|
| 11d9dbb7b7 | |||
| 896fb5d6a5 | |||
| e3d3b4b5a4 | |||
| 08e5943efc | |||
| 7068894be3 |
@@ -88,6 +88,7 @@ objs
|
||||
# Build outputs
|
||||
/build*/
|
||||
/visual_studio/
|
||||
/originbuild/
|
||||
|
||||
# Fuzzer outputs generated by instructions in fuzz/Fuzzing.md
|
||||
/corpus.zip
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Implementation selection
|
||||
#
|
||||
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell icelake arm64 ppc64)
|
||||
set(SIMDJSON_ALL_IMPLEMENTATIONS fallback westmere haswell icelake arm64 ppc64 rvv)
|
||||
|
||||
set(
|
||||
SIMDJSON_IMPLEMENTATION ""
|
||||
@@ -15,7 +15,7 @@ set(
|
||||
SIMDJSON_EXCLUDE_IMPLEMENTATION ""
|
||||
CACHE STRING "\
|
||||
Semicolon-separated list of implementations to exclude \
|
||||
(icelake/haswell/westmere/arm64/ppc64/fallback). By default, excludes any \
|
||||
(icelake/haswell/westmere/arm64/ppc64/rvv/fallback). By default, excludes any \
|
||||
implementations that are unsupported at compile time or cannot be selected at \
|
||||
runtime."
|
||||
)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "simdjson/lsx.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx)
|
||||
#include "simdjson/lasx.h"
|
||||
#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv)
|
||||
#include "simdjson/rvv.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)
|
||||
namespace rvv {}
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
@@ -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)
|
||||
#include "simdjson/rvv/implementation.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
@@ -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)
|
||||
#include "simdjson/rvv/ondemand.h"
|
||||
#else
|
||||
#error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#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_FOR(IMPL) SIMDJSON_CAT(SIMDJSON_IMPLEMENTATION_ID_, IMPL)
|
||||
#define SIMDJSON_IMPLEMENTATION_ID SIMDJSON_IMPLEMENTATION_ID_FOR(SIMDJSON_IMPLEMENTATION)
|
||||
@@ -23,6 +24,15 @@
|
||||
// in which we include them.
|
||||
//
|
||||
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_RVV
|
||||
#define SIMDJSON_IMPLEMENTATION_RVV (SIMDJSON_IS_RISCV64 && SIMDJSON_IS_RVV)
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV && SIMDJSON_IS_RISCV64 && SIMDJSON_IS_RVV
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_RVV 1
|
||||
#else
|
||||
#define SIMDJSON_CAN_ALWAYS_RUN_RVV 0
|
||||
#endif
|
||||
|
||||
#ifndef SIMDJSON_IMPLEMENTATION_ARM64
|
||||
#define SIMDJSON_IMPLEMENTATION_ARM64 (SIMDJSON_IS_ARM64)
|
||||
#endif
|
||||
@@ -128,7 +138,7 @@
|
||||
|
||||
// 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
|
||||
// if anything at all except fallback can always run, then disable fallback.
|
||||
#define SIMDJSON_IMPLEMENTATION_FALLBACK 0
|
||||
#else
|
||||
@@ -154,6 +164,8 @@
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION lsx
|
||||
#elif SIMDJSON_CAN_ALWAYS_RUN_LASX
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION lasx
|
||||
#elif SIMDJSON_CAN_ALWAYS_RUN_RVV
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION rvv
|
||||
#elif SIMDJSON_CAN_ALWAYS_RUN_FALLBACK
|
||||
#define SIMDJSON_BUILTIN_IMPLEMENTATION fallback
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef SIMDJSON_RVV_H
|
||||
#define SIMDJSON_RVV_H
|
||||
|
||||
#include "simdjson/rvv/begin.h"
|
||||
#include "simdjson/generic/amalgamated.h"
|
||||
#include "simdjson/rvv/end.h"
|
||||
|
||||
#endif // SIMDJSON_RVV_H
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef SIMDJSON_RVV_BASE_H
|
||||
#define SIMDJSON_RVV_BASE_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
namespace simdjson {
|
||||
namespace rvv {
|
||||
|
||||
class implementation;
|
||||
|
||||
namespace {
|
||||
namespace simd {
|
||||
template <typename T> struct simd8;
|
||||
template <typename T> struct simd8x64;
|
||||
} // namespace simd
|
||||
} // unnamed namespace
|
||||
} // namespace rvv
|
||||
} // namespace simdjson
|
||||
#endif // SIMDJSON_RVV_BASE_H
|
||||
@@ -0,0 +1,13 @@
|
||||
#define SIMDJSON_IMPLEMENTATION rvv
|
||||
|
||||
// include RVV intrinsics and definitions
|
||||
#include <riscv_vector.h>
|
||||
#include "simdjson/rvv/base.h"
|
||||
#include "simdjson/rvv/intrinsics.h"
|
||||
#include "simdjson/rvv/bitmanipulation.h"
|
||||
#include "simdjson/rvv/bitmask.h"
|
||||
#include "simdjson/rvv/numberparsing_defs.h"
|
||||
#include "simdjson/rvv/simd.h"
|
||||
#include "simdjson/rvv/stringparsing_defs.h"
|
||||
|
||||
#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef SIMDJSON_RVV_BITMANIPULATION_H
|
||||
#define SIMDJSON_RVV_BITMANIPULATION_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv {
|
||||
namespace {
|
||||
|
||||
/* result might be undefined when input_num is zero */
|
||||
simdjson_inline int leading_zeroes(uint64_t input_num) {
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
unsigned long leading_zero = 0;
|
||||
if (_BitScanReverse64(&leading_zero, input_num))
|
||||
return (int)(63 - leading_zero);
|
||||
else
|
||||
return 64;
|
||||
#else
|
||||
return __builtin_clzll(input_num);
|
||||
#endif
|
||||
}
|
||||
|
||||
simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) {
|
||||
return input_num & (input_num - 1);
|
||||
}
|
||||
|
||||
simdjson_inline int count_ones(uint64_t input_num) {
|
||||
return __builtin_popcountll(input_num);
|
||||
}
|
||||
|
||||
|
||||
inline simdjson::internal::value128 full_multiplication(uint64_t a, uint64_t b) {
|
||||
#if __SIZEOF_INT128__
|
||||
unsigned __int128 p = (unsigned __int128)a * b;
|
||||
return { (uint64_t)p, (uint64_t)(p >> 64) };
|
||||
#else
|
||||
uint64_t lo = a * b;
|
||||
uint64_t a0 = (uint32_t)a, a1 = a >> 32;
|
||||
uint64_t b0 = (uint32_t)b, b1 = b >> 32;
|
||||
uint64_t mid1 = a0 * b1;
|
||||
uint64_t mid2 = a1 * b0;
|
||||
uint64_t carry = ((mid1 & 0xFFFFFFFF) + (mid2 & 0xFFFFFFFF) + (lo >> 32)) >> 32;
|
||||
uint64_t hi = a1 * b1 + (mid1 >> 32) + (mid2 >> 32) + carry;
|
||||
return { lo, hi };
|
||||
#endif
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
} // namespace rvv
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_BITMANIPULATION_H
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#undef SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT
|
||||
#undef SIMDJSON_IMPLEMENTATION
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef SIMDJSON_RVV_IMPLEMENTATION_H
|
||||
#define SIMDJSON_RVV_IMPLEMENTATION_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/base.h"
|
||||
#include "simdjson/implementation.h"
|
||||
#include "simdjson/internal/instruction_set.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv {
|
||||
|
||||
class implementation final: public simdjson::implementation {
|
||||
public:
|
||||
simdjson_inline implementation() : simdjson::implementation("rvv", "RISC-V Vector Extension", 0) {}
|
||||
simdjson_warn_unused error_code create_dom_parser_implementation(
|
||||
size_t capacity,
|
||||
size_t max_depth,
|
||||
std::unique_ptr<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
|
||||
} // namespace simdjson
|
||||
|
||||
#endif // SIMDJSON_RVV_IMPLEMENTATION_H
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef SIMDJSON_RVV_INTRINSICS_H
|
||||
#define SIMDJSON_RVV_INTRINSICS_H
|
||||
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv/base.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#endif // SIMDJSON_RVV_INTRINSICS_H
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef SIMDJSON_RVV_ONDEMAND_H
|
||||
#define SIMDJSON_RVV_ONDEMAND_H
|
||||
|
||||
#include "simdjson/rvv/begin.h"
|
||||
#include "simdjson/generic/ondemand/amalgamated.h"
|
||||
#include "simdjson/rvv/end.h"
|
||||
|
||||
#endif // SIMDJSON_RVV_ONDEMAND_H
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
#ifndef SIMDJSON_RVV_SIMD_H
|
||||
#define SIMDJSON_RVV_SIMD_H
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include "simdjson/rvv/base.h"
|
||||
#include "simdjson/rvv/intrinsics.h"
|
||||
#include "simdjson/internal/simdprune_tables.h"
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv {
|
||||
namespace {
|
||||
namespace simd {
|
||||
|
||||
// ---------- 128-bit fixed vectors ----------
|
||||
using vuint8x16 = vuint8m1_t __attribute__((riscv_rvv_vector_bits(128)));
|
||||
using vint8x16 = vint8m1_t __attribute__((riscv_rvv_vector_bits(128)));
|
||||
using vbool8x16 = vbool8_t;
|
||||
static constexpr size_t fixed_vl = 16;
|
||||
|
||||
// ---------- forward ----------
|
||||
template<typename T> struct simd8;
|
||||
template<typename T> struct simd8x64;
|
||||
|
||||
// ---------- base<Child> ----------
|
||||
template<typename Child>
|
||||
struct base {
|
||||
vuint8x16 value{};
|
||||
base() = default;
|
||||
base(vuint8x16 v) : value(v) {}
|
||||
operator vuint8x16() const { return value; }
|
||||
operator vuint8x16&() { return value; }
|
||||
|
||||
simdjson_inline Child operator|(const Child o) const { return __riscv_vor_vv_u8m1(value, o, fixed_vl); }
|
||||
simdjson_inline Child operator&(const Child o) const { return __riscv_vand_vv_u8m1(value, o, fixed_vl); }
|
||||
simdjson_inline Child operator^(const Child o) const { return __riscv_vxor_vv_u8m1(value, o, fixed_vl); }
|
||||
simdjson_inline Child bit_andnot(const Child o) const { return __riscv_vandn_vv_u8m1(value, o, fixed_vl); }
|
||||
|
||||
simdjson_inline Child& operator|=(const Child o) { auto* c = static_cast<Child*>(this); *c = *c | o; return *c; }
|
||||
simdjson_inline Child& operator&=(const Child o) { auto* c = static_cast<Child*>(this); *c = *c & o; return *c; }
|
||||
simdjson_inline Child& operator^=(const Child o) { auto* c = static_cast<Child*>(this); *c = *c ^ o; return *c; }
|
||||
};
|
||||
|
||||
// ---------- base8<T,Mask> ----------
|
||||
template<typename T, typename Mask = simd8<bool>>
|
||||
struct base8 : base<simd8<T>> {
|
||||
using base<simd8<T>>::value;
|
||||
using bitmask_t = uint32_t;
|
||||
base8() = default;
|
||||
base8(vuint8x16 v) : base<simd8<T>>(v) {}
|
||||
|
||||
friend simdjson_inline Mask operator==(const simd8<T> a, const simd8<T> b) {
|
||||
return simd8<bool>(__riscv_vmseq_vv_u8m1_b8(a, b, fixed_vl));
|
||||
}
|
||||
template<int N=1>
|
||||
simdjson_inline simd8<T> prev(const simd8<T> prev_chunk) const {
|
||||
return __riscv_vslideup_vx_u8m1(prev_chunk, value, fixed_vl - N, 2 * fixed_vl);
|
||||
}
|
||||
};
|
||||
|
||||
// ---------- simd8<bool> ----------
|
||||
template<>
|
||||
struct simd8<bool> : base8<bool> {
|
||||
simd8() = default;
|
||||
simd8(vuint8x16 v) : base8(v) {}
|
||||
simd8(vbool8_t m) : base8(__riscv_vmerge_vvm_u8m1(
|
||||
__riscv_vmv_v_x_u8m1(0, fixed_vl),
|
||||
__riscv_vmv_v_x_u8m1(0xFFu, fixed_vl),
|
||||
m, fixed_vl)) {}
|
||||
|
||||
static simdjson_inline simd8<bool> splat(bool b) {
|
||||
return __riscv_vmv_v_x_u8m1(uint8_t(-b), fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8(bool b) : simd8(splat(b)) {}
|
||||
|
||||
simdjson_inline int to_bitmask() const {
|
||||
vuint8x16 bits = __riscv_vand_vx_u8m1(value, 0xFFu, fixed_vl);
|
||||
vbool8x16 mask = __riscv_vmseq_vx_u8m1_b8(bits, 0xFFu, fixed_vl);
|
||||
return __riscv_vcpop_m_b8(mask, fixed_vl);
|
||||
}
|
||||
simdjson_inline bool any_bits_set_anywhere() const {
|
||||
return to_bitmask() != 0;
|
||||
}
|
||||
simdjson_inline simd8<bool> operator~() const { return *this ^ splat(true); }
|
||||
};
|
||||
|
||||
// ---------- simd8<uint8_t> ----------
|
||||
template<>
|
||||
struct simd8<uint8_t> : base8<uint8_t> {
|
||||
simd8() = default;
|
||||
simd8(vuint8x16 v) : base8(v) {}
|
||||
static simdjson_inline simd8<uint8_t> splat(uint8_t v) {
|
||||
return __riscv_vmv_v_x_u8m1(v, fixed_vl);
|
||||
}
|
||||
static simdjson_inline simd8<uint8_t> zero() { return splat(0); }
|
||||
static simdjson_inline simd8<uint8_t> load(const uint8_t* p) {
|
||||
return __riscv_vle8_v_u8m1(p, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8(uint8_t v) : simd8(splat(v)) {}
|
||||
simdjson_inline simd8(const uint8_t* p) : simd8(load(p)) {}
|
||||
|
||||
simdjson_inline void store(uint8_t* p) const {
|
||||
__riscv_vse8_v_u8m1(p, value, fixed_vl);
|
||||
}
|
||||
|
||||
simdjson_inline simd8<uint8_t> operator+(const simd8<uint8_t> o) const {
|
||||
return __riscv_vadd_vv_u8m1(value, o, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<uint8_t> operator-(const simd8<uint8_t> o) const {
|
||||
return __riscv_vsub_vv_u8m1(value, o, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<uint8_t>& operator+=(const simd8<uint8_t> o) {
|
||||
*this = *this + o; return *this;
|
||||
}
|
||||
simdjson_inline simd8<uint8_t>& operator-=(const simd8<uint8_t> o) {
|
||||
*this = *this - o; return *this;
|
||||
}
|
||||
|
||||
simdjson_inline simd8<uint8_t> saturating_add(const simd8<uint8_t> o) const {
|
||||
return __riscv_vsaddu_vv_u8m1(value, o, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<uint8_t> saturating_sub(const simd8<uint8_t> o) const {
|
||||
return __riscv_vssubu_vv_u8m1(value, o, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<uint8_t> max_val(const simd8<uint8_t> o) const {
|
||||
return __riscv_vmaxu_vv_u8m1(value, o, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<uint8_t> min_val(const simd8<uint8_t> o) const {
|
||||
return __riscv_vminu_vv_u8m1(value, o, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<bool> operator>(const simd8<uint8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmsgtu_vv_u8m1_b8(value, o, fixed_vl));
|
||||
}
|
||||
simdjson_inline simd8<bool> operator<(const simd8<uint8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmsgtu_vv_u8m1_b8(o, value, fixed_vl));
|
||||
}
|
||||
simdjson_inline simd8<bool> operator<=(const simd8<uint8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmsleu_vv_u8m1_b8(value, o, fixed_vl));
|
||||
}
|
||||
simdjson_inline simd8<bool> operator>=(const simd8<uint8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmsleu_vv_u8m1_b8(o, value, fixed_vl));
|
||||
}
|
||||
template<int NS>
|
||||
simdjson_inline simd8<uint8_t> shr() const {
|
||||
return __riscv_vsrl_vx_u8m1(value, NS, fixed_vl);
|
||||
}
|
||||
template<int NS>
|
||||
simdjson_inline simd8<uint8_t> shl() const {
|
||||
return __riscv_vsll_vx_u8m1(value, NS, fixed_vl);
|
||||
}
|
||||
template <typename Ret>
|
||||
simdjson_inline simd8<Ret> lookup_16(const Ret* table) const {
|
||||
alignas(16) uint8_t idx[16];
|
||||
store(idx);
|
||||
alignas(16) Ret res[16];
|
||||
for (int i = 0; i < 16; ++i) res[i] = table[idx[i]];
|
||||
return simd8<Ret>::load(reinterpret_cast<const Ret*>(res));
|
||||
}
|
||||
simdjson_inline void compress(uint16_t mask, uint8_t* out) const {
|
||||
alignas(16) uint8_t tmp[16];
|
||||
store(tmp);
|
||||
for (int i = 0, j = 0; i < 16; ++i)
|
||||
if (mask & (1u << i)) out[j++] = tmp[i];
|
||||
}
|
||||
simdjson_inline uint64_t gt_bits(uint8_t max_value) const {
|
||||
return (*this > splat(max_value)).to_bitmask();
|
||||
}
|
||||
simdjson_inline uint64_t gt_bits(const simd8<uint8_t>& max_vec) const {
|
||||
return (*this > max_vec).to_bitmask();
|
||||
}
|
||||
simdjson_inline bool any_bits_set_anywhere() const {
|
||||
return (*this > zero()).any_bits_set_anywhere();
|
||||
}
|
||||
};
|
||||
|
||||
// ---------- simd8<int8_t> ----------
|
||||
template<>
|
||||
struct simd8<int8_t> {
|
||||
vint8x16 value{};
|
||||
simd8() = default;
|
||||
simd8(vint8x16 v) : value(v) {}
|
||||
static simdjson_inline simd8<int8_t> splat(int8_t v) {
|
||||
return __riscv_vmv_v_x_i8m1(v, fixed_vl);
|
||||
}
|
||||
static simdjson_inline simd8<int8_t> zero() { return splat(0); }
|
||||
static simdjson_inline simd8<int8_t> load(const int8_t* p) {
|
||||
return __riscv_vle8_v_i8m1(p, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8(int8_t v) : simd8(splat(v)) {}
|
||||
simdjson_inline simd8(const int8_t* p) : simd8(load(p)) {}
|
||||
|
||||
simdjson_inline void store(int8_t* p) const {
|
||||
__riscv_vse8_v_i8m1(p, value, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<int8_t> operator+(const simd8<int8_t> o) const {
|
||||
return __riscv_vadd_vv_i8m1(value, o.value, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<int8_t> operator-(const simd8<int8_t> o) const {
|
||||
return __riscv_vsub_vv_i8m1(value, o.value, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<int8_t> max_val(const simd8<int8_t> o) const {
|
||||
return __riscv_vmax_vv_i8m1(value, o.value, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<int8_t> min_val(const simd8<int8_t> o) const {
|
||||
return __riscv_vmin_vv_i8m1(value, o.value, fixed_vl);
|
||||
}
|
||||
simdjson_inline simd8<bool> operator>(const simd8<int8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmsgt_vv_i8m1_b8(value, o.value, fixed_vl));
|
||||
}
|
||||
simdjson_inline simd8<bool> operator<(const simd8<int8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmsgt_vv_i8m1_b8(o.value, value, fixed_vl));
|
||||
}
|
||||
simdjson_inline simd8<bool> operator==(const simd8<int8_t> o) const {
|
||||
return simd8<bool>(__riscv_vmseq_vv_i8m1_b8(value, o.value, fixed_vl));
|
||||
}
|
||||
template<int N=1>
|
||||
simdjson_inline simd8<int8_t> prev(const simd8<int8_t> prev_chunk) const {
|
||||
return __riscv_vslideup_vx_i8m1(prev_chunk.value, value, fixed_vl - N, 2 * fixed_vl);
|
||||
}
|
||||
};
|
||||
|
||||
// ---------- simd8x64<T> ----------
|
||||
template<typename T>
|
||||
struct simd8x64 {
|
||||
static constexpr int NUM_CHUNKS = 64 / sizeof(simd8<T>);
|
||||
static_assert(NUM_CHUNKS == 4, "RVV kernel uses 4×128-bit chunks per 64-byte block.");
|
||||
const simd8<T> chunks[4];
|
||||
|
||||
simd8x64(const simd8x64&) = delete;
|
||||
simd8x64& operator=(const simd8x64&) = delete;
|
||||
simd8x64() = delete;
|
||||
|
||||
simdjson_inline simd8x64(const simd8<T> c0, const simd8<T> c1,
|
||||
const simd8<T> c2, const simd8<T> c3)
|
||||
: chunks{c0, c1, c2, c3} {}
|
||||
simdjson_inline simd8x64(const T* ptr)
|
||||
: chunks{simd8<T>::load(ptr),
|
||||
simd8<T>::load(ptr + 16),
|
||||
simd8<T>::load(ptr + 32),
|
||||
simd8<T>::load(ptr + 48)} {}
|
||||
|
||||
simdjson_inline void store(T* ptr) const {
|
||||
chunks[0].store(ptr);
|
||||
chunks[1].store(ptr + 16);
|
||||
chunks[2].store(ptr + 32);
|
||||
chunks[3].store(ptr + 48);
|
||||
}
|
||||
simdjson_inline simd8<T> reduce_or() const {
|
||||
return (chunks[0] | chunks[1]) | (chunks[2] | chunks[3]);
|
||||
}
|
||||
simdjson_inline uint64_t to_bitmask() const {
|
||||
uint16_t m0 = uint16_t(chunks[0].to_bitmask());
|
||||
uint16_t m1 = uint16_t(chunks[1].to_bitmask());
|
||||
uint16_t m2 = uint16_t(chunks[2].to_bitmask());
|
||||
uint16_t m3 = uint16_t(chunks[3].to_bitmask());
|
||||
return m0 | (uint64_t(m1) << 16) | (uint64_t(m2) << 32) | (uint64_t(m3) << 48);
|
||||
}
|
||||
simdjson_inline uint64_t eq(const T m) const {
|
||||
simd8<T> spl = simd8<T>::splat(m);
|
||||
return simd8x64<bool>(chunks[0] == spl,
|
||||
chunks[1] == spl,
|
||||
chunks[2] == spl,
|
||||
chunks[3] == spl).to_bitmask();
|
||||
}
|
||||
simdjson_inline uint64_t lteq(const T m) const {
|
||||
simd8<T> spl = simd8<T>::splat(m);
|
||||
return simd8x64<bool>(chunks[0] <= spl,
|
||||
chunks[1] <= spl,
|
||||
chunks[2] <= spl,
|
||||
chunks[3] <= spl).to_bitmask();
|
||||
}
|
||||
simdjson_inline uint64_t compress(uint64_t mask, T* out) const {
|
||||
using internal::BitsSetTable256mul2;
|
||||
uint32_t m0 = uint32_t(mask);
|
||||
uint32_t m1 = uint32_t(mask >> 16);
|
||||
uint32_t m2 = uint32_t(mask >> 32);
|
||||
uint32_t m3 = uint32_t(mask >> 48);
|
||||
|
||||
int pop0 = BitsSetTable256mul2[uint8_t(m0)];
|
||||
int pop1 = BitsSetTable256mul2[uint8_t(m1)];
|
||||
int pop2 = BitsSetTable256mul2[uint8_t(m2)];
|
||||
|
||||
chunks[0].compress(uint16_t(m0), out);
|
||||
chunks[1].compress(uint16_t(m1), out + 16 - pop0);
|
||||
chunks[2].compress(uint16_t(m2), out + 32 - pop0 - pop1);
|
||||
chunks[3].compress(uint16_t(m3), out + 48 - pop0 - pop1 - pop2);
|
||||
return 64 - __builtin_popcountll(mask);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace simd
|
||||
} // unnamed namespace
|
||||
} // namespace rvv
|
||||
} // namespace simdjson
|
||||
|
||||
|
||||
#endif // SIMDJSON_RVV_SIMD_H
|
||||
@@ -71,7 +71,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', 'westmere', 'fallback', 'rvv' ]
|
||||
GENERIC_INCLUDE = "simdjson/generic"
|
||||
GENERIC_SRC = "generic"
|
||||
BUILTIN = "simdjson/builtin"
|
||||
@@ -358,7 +358,6 @@ class Amalgamator:
|
||||
self.include_stack.append(file)
|
||||
|
||||
file.processed = False
|
||||
|
||||
self.write(f"/* begin file {self.file_to_str(file)} */")
|
||||
|
||||
if file == BUILTIN_BEGIN_H:
|
||||
|
||||
@@ -21,6 +21,19 @@ bool implementation::supported_by_runtime_system() const {
|
||||
|
||||
#define SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV
|
||||
#include <simdjson/rvv/implementation.h>
|
||||
namespace simdjson {
|
||||
namespace internal {
|
||||
static const rvv::implementation* get_rvv_singleton() {
|
||||
static const rvv::implementation rvv_singleton{};
|
||||
return &rvv_singleton;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace simdjson
|
||||
#endif // SIMDJSON_IMPLEMENTATION_RVV
|
||||
|
||||
|
||||
#if SIMDJSON_IMPLEMENTATION_ARM64
|
||||
#include <simdjson/arm64/implementation.h>
|
||||
namespace simdjson {
|
||||
@@ -130,6 +143,7 @@ namespace internal {
|
||||
+ SIMDJSON_IMPLEMENTATION_HASWELL + SIMDJSON_IMPLEMENTATION_WESTMERE \
|
||||
+ SIMDJSON_IMPLEMENTATION_ARM64 + SIMDJSON_IMPLEMENTATION_PPC64 \
|
||||
+ SIMDJSON_IMPLEMENTATION_LSX + SIMDJSON_IMPLEMENTATION_LASX \
|
||||
+ SIMDJSON_IMPLEMENTATION_RVV \
|
||||
+ SIMDJSON_IMPLEMENTATION_FALLBACK == 1)
|
||||
|
||||
#if SIMDJSON_SINGLE_IMPLEMENTATION
|
||||
@@ -156,6 +170,9 @@ namespace internal {
|
||||
#if SIMDJSON_IMPLEMENTATION_LASX
|
||||
get_lasx_singleton();
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV
|
||||
get_rvv_singleton();
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
get_fallback_singleton();
|
||||
#endif
|
||||
@@ -216,6 +233,9 @@ static const std::initializer_list<const implementation *>& get_available_implem
|
||||
#if SIMDJSON_IMPLEMENTATION_LASX
|
||||
get_lasx_singleton(),
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV
|
||||
get_rvv_singleton(),
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
get_fallback_singleton(),
|
||||
#endif
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#ifndef SIMDJSON_SRC_RVV_CPP
|
||||
#define SIMDJSON_SRC_RVV_CPP
|
||||
|
||||
#ifndef SIMDJSON_CONDITIONAL_INCLUDE
|
||||
#include <base.h>
|
||||
#endif // SIMDJSON_CONDITIONAL_INCLUDE
|
||||
|
||||
|
||||
#include <simdjson/rvv.h>
|
||||
#include <simdjson/rvv/implementation.h>
|
||||
|
||||
|
||||
|
||||
namespace simdjson {
|
||||
namespace rvv {
|
||||
error_code implementation::create_dom_parser_implementation(
|
||||
size_t, size_t,
|
||||
std::unique_ptr<simdjson::internal::dom_parser_implementation>&) const noexcept {
|
||||
return error_code::UNSUPPORTED_ARCHITECTURE;
|
||||
}
|
||||
} // namespace rvv
|
||||
} // namespace simdjson
|
||||
#endif // SIMDJSON_SRC_RVV_CPP
|
||||
@@ -41,6 +41,9 @@ SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS
|
||||
#if SIMDJSON_IMPLEMENTATION_LASX
|
||||
#include <lasx.cpp>
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_RVV
|
||||
#include <rvv.cpp>
|
||||
#endif
|
||||
#if SIMDJSON_IMPLEMENTATION_FALLBACK
|
||||
#include <fallback.cpp>
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user