vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b
This commit is contained in:
+45
@@ -0,0 +1,45 @@
|
||||
# Building RISC-V Target with Cmake #
|
||||
|
||||
> **Warning**
|
||||
> Runtime rvv detection (using `hwcap`) requires linux kernel 6.5 or newer.
|
||||
>
|
||||
> When running on older kernels, we fall back to compile-time detection, potentially this can cause crashes if rvv is enabled at compile but not supported by the target cpu.
|
||||
> Therefore if older kernel support is needed, rvv should be disabled if the target cpu does not support it.
|
||||
## Prerequisite: Build RISC-V Clang Toolchain and QEMU ##
|
||||
|
||||
If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version).
|
||||
|
||||
```bash
|
||||
./prepare_riscv_toolchain_qemu.sh
|
||||
```
|
||||
|
||||
After running script, clang & qemu are built in `build-toolchain-qemu/riscv-clang/` & `build-toolchain-qemu/riscv-qemu/`.
|
||||
|
||||
`build-toolchain-qemu/riscv-clang/` is your `TOOLCHAIN_PATH`.
|
||||
`build-toolchain-qemu/riscv-qemu/bin/qemu-riscv64` is your `QEMU_PATH`.
|
||||
|
||||
You can also download the prebuilt toolchain & qemu from [the release page](https://github.com/sifive/prepare-riscv-toolchain-qemu/releases), and enjoy using them.
|
||||
|
||||
## Cross-Compile for RISC-V Target ##
|
||||
|
||||
```bash
|
||||
cmake -G Ninja -B ./build-riscv \
|
||||
-D CMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake \
|
||||
-D CMAKE_INSTALL_PREFIX=./build-riscv/install \
|
||||
-D TOOLCHAIN_PATH={TOOLCHAIN_PATH} \
|
||||
-D QEMU_PATH={QEMU_PATH} \
|
||||
.
|
||||
|
||||
cmake --build ./build-riscv
|
||||
```
|
||||
|
||||
Disable the option if there is no RVV support:
|
||||
```
|
||||
-D WITH_RVV=OFF
|
||||
```
|
||||
|
||||
## Run Unittests on User Mode QEMU ##
|
||||
|
||||
```bash
|
||||
cd ./build-riscv && ctest --verbose
|
||||
```
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
/* adler32_rvv.c - RVV version of adler32
|
||||
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
|
||||
* Contributed by Alex Chiang <alex.chiang@sifive.com>
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef RISCV_RVV
|
||||
|
||||
#include <riscv_vector.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "adler32_p.h"
|
||||
|
||||
static inline uint32_t adler32_rvv_impl(uint32_t adler, uint8_t* restrict dst, const uint8_t *src, size_t len, int COPY) {
|
||||
/* split Adler-32 into component sums */
|
||||
uint32_t sum2 = (adler >> 16) & 0xffff;
|
||||
adler &= 0xffff;
|
||||
|
||||
/* in case user likes doing a byte at a time, keep it fast */
|
||||
if (len == 1) {
|
||||
if (COPY) memcpy(dst, src, 1);
|
||||
return adler32_len_1(adler, src, sum2);
|
||||
}
|
||||
|
||||
/* initial Adler-32 value (deferred check for len == 1 speed) */
|
||||
if (src == NULL)
|
||||
return 1L;
|
||||
|
||||
/* in case short lengths are provided, keep it somewhat fast */
|
||||
if (len < 16) {
|
||||
if (COPY) memcpy(dst, src, len);
|
||||
return adler32_len_16(adler, src, len, sum2);
|
||||
}
|
||||
|
||||
size_t left = len;
|
||||
size_t vl = __riscv_vsetvlmax_e8m1();
|
||||
vl = vl > 256 ? 256 : vl;
|
||||
vuint32m4_t v_buf32_accu = __riscv_vmv_v_x_u32m4(0, vl);
|
||||
vuint32m4_t v_adler32_prev_accu = __riscv_vmv_v_x_u32m4(0, vl);
|
||||
vuint16m2_t v_buf16_accu;
|
||||
|
||||
/*
|
||||
* We accumulate 8-bit data, and to prevent overflow, we have to use a 32-bit accumulator.
|
||||
* However, adding 8-bit data into a 32-bit accumulator isn't efficient. We use 16-bit & 32-bit
|
||||
* accumulators to boost performance.
|
||||
*
|
||||
* The block_size is the largest multiple of vl that <= 256, because overflow would occur when
|
||||
* vl > 256 (255 * 256 <= UINT16_MAX).
|
||||
*
|
||||
* We accumulate 8-bit data into a 16-bit accumulator and then
|
||||
* move the data into the 32-bit accumulator at the last iteration.
|
||||
*/
|
||||
size_t block_size = (256 / vl) * vl;
|
||||
size_t nmax_limit = (NMAX / block_size);
|
||||
size_t cnt = 0;
|
||||
while (left >= block_size) {
|
||||
v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl);
|
||||
size_t subprob = block_size;
|
||||
while (subprob > 0) {
|
||||
vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(src, vl);
|
||||
if (COPY) __riscv_vse8_v_u8m1(dst, v_buf8, vl);
|
||||
v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl);
|
||||
v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl);
|
||||
src += vl;
|
||||
if (COPY) dst += vl;
|
||||
subprob -= vl;
|
||||
}
|
||||
v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, block_size / vl, v_buf32_accu, vl);
|
||||
v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl);
|
||||
left -= block_size;
|
||||
/* do modulo once each block of NMAX size */
|
||||
if (++cnt >= nmax_limit) {
|
||||
v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
/* the left len <= 256 now, we can use 16-bit accum safely */
|
||||
v_buf16_accu = __riscv_vmv_v_x_u16m2(0, vl);
|
||||
size_t res = left;
|
||||
while (left >= vl) {
|
||||
vuint8m1_t v_buf8 = __riscv_vle8_v_u8m1(src, vl);
|
||||
if (COPY) __riscv_vse8_v_u8m1(dst, v_buf8, vl);
|
||||
v_adler32_prev_accu = __riscv_vwaddu_wv_u32m4(v_adler32_prev_accu, v_buf16_accu, vl);
|
||||
v_buf16_accu = __riscv_vwaddu_wv_u16m2(v_buf16_accu, v_buf8, vl);
|
||||
src += vl;
|
||||
if (COPY) dst += vl;
|
||||
left -= vl;
|
||||
}
|
||||
v_adler32_prev_accu = __riscv_vmacc_vx_u32m4(v_adler32_prev_accu, res / vl, v_buf32_accu, vl);
|
||||
v_adler32_prev_accu = __riscv_vremu_vx_u32m4(v_adler32_prev_accu, BASE, vl);
|
||||
v_buf32_accu = __riscv_vwaddu_wv_u32m4(v_buf32_accu, v_buf16_accu, vl);
|
||||
|
||||
vuint32m4_t v_seq = __riscv_vid_v_u32m4(vl);
|
||||
vuint32m4_t v_rev_seq = __riscv_vrsub_vx_u32m4(v_seq, vl, vl);
|
||||
vuint32m4_t v_sum32_accu = __riscv_vmul_vv_u32m4(v_buf32_accu, v_rev_seq, vl);
|
||||
|
||||
v_sum32_accu = __riscv_vadd_vv_u32m4(v_sum32_accu, __riscv_vmul_vx_u32m4(v_adler32_prev_accu, vl, vl), vl);
|
||||
|
||||
vuint32m1_t v_sum2_sum = __riscv_vmv_s_x_u32m1(0, vl);
|
||||
v_sum2_sum = __riscv_vredsum_vs_u32m4_u32m1(v_sum32_accu, v_sum2_sum, vl);
|
||||
uint32_t sum2_sum = __riscv_vmv_x_s_u32m1_u32(v_sum2_sum);
|
||||
|
||||
sum2 += (sum2_sum + adler * (len - left));
|
||||
|
||||
vuint32m1_t v_adler_sum = __riscv_vmv_s_x_u32m1(0, vl);
|
||||
v_adler_sum = __riscv_vredsum_vs_u32m4_u32m1(v_buf32_accu, v_adler_sum, vl);
|
||||
uint32_t adler_sum = __riscv_vmv_x_s_u32m1_u32(v_adler_sum);
|
||||
|
||||
adler += adler_sum;
|
||||
|
||||
while (left--) {
|
||||
if (COPY) *dst++ = *src;
|
||||
adler += *src++;
|
||||
sum2 += adler;
|
||||
}
|
||||
|
||||
sum2 %= BASE;
|
||||
adler %= BASE;
|
||||
|
||||
return adler | (sum2 << 16);
|
||||
}
|
||||
|
||||
Z_INTERNAL uint32_t adler32_fold_copy_rvv(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len) {
|
||||
return adler32_rvv_impl(adler, dst, src, len, 1);
|
||||
}
|
||||
|
||||
Z_INTERNAL uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len) {
|
||||
return adler32_rvv_impl(adler, NULL, buf, len, 0);
|
||||
}
|
||||
|
||||
#endif // RISCV_RVV
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
/* chunkset_rvv.c - RVV version of chunkset
|
||||
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
|
||||
* Contributed by Alex Chiang <alex.chiang@sifive.com>
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
#include <riscv_vector.h>
|
||||
#include "zbuild.h"
|
||||
|
||||
/*
|
||||
* RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC,
|
||||
* so we prefer using large size chunk and copy memory as much as possible.
|
||||
*/
|
||||
#define CHUNK_SIZE 32
|
||||
|
||||
#define HAVE_CHUNKMEMSET_2
|
||||
#define HAVE_CHUNKMEMSET_4
|
||||
#define HAVE_CHUNKMEMSET_8
|
||||
|
||||
#define CHUNK_MEMSET_RVV_IMPL(elen) \
|
||||
do { \
|
||||
size_t vl, len = CHUNK_SIZE / sizeof(uint##elen##_t); \
|
||||
uint##elen##_t val = *(uint##elen##_t*)from; \
|
||||
uint##elen##_t* chunk_p = (uint##elen##_t*)chunk; \
|
||||
do { \
|
||||
vl = __riscv_vsetvl_e##elen##m4(len); \
|
||||
vuint##elen##m4_t v_val = __riscv_vmv_v_x_u##elen##m4(val, vl); \
|
||||
__riscv_vse##elen##_v_u##elen##m4(chunk_p, v_val, vl); \
|
||||
len -= vl; chunk_p += vl; \
|
||||
} while (len > 0); \
|
||||
} while (0)
|
||||
|
||||
/* We don't have a 32-byte datatype for RISC-V arch. */
|
||||
typedef struct chunk_s {
|
||||
uint64_t data[4];
|
||||
} chunk_t;
|
||||
|
||||
static inline void chunkmemset_2(uint8_t *from, chunk_t *chunk) {
|
||||
CHUNK_MEMSET_RVV_IMPL(16);
|
||||
}
|
||||
|
||||
static inline void chunkmemset_4(uint8_t *from, chunk_t *chunk) {
|
||||
CHUNK_MEMSET_RVV_IMPL(32);
|
||||
}
|
||||
|
||||
static inline void chunkmemset_8(uint8_t *from, chunk_t *chunk) {
|
||||
CHUNK_MEMSET_RVV_IMPL(64);
|
||||
}
|
||||
|
||||
static inline void loadchunk(uint8_t const *s, chunk_t *chunk) {
|
||||
memcpy(chunk->data, (uint8_t *)s, CHUNK_SIZE);
|
||||
}
|
||||
|
||||
static inline void storechunk(uint8_t *out, chunk_t *chunk) {
|
||||
memcpy(out, chunk->data, CHUNK_SIZE);
|
||||
}
|
||||
|
||||
#define CHUNKSIZE chunksize_rvv
|
||||
#define CHUNKCOPY chunkcopy_rvv
|
||||
#define CHUNKUNROLL chunkunroll_rvv
|
||||
#define CHUNKMEMSET chunkmemset_rvv
|
||||
#define CHUNKMEMSET_SAFE chunkmemset_safe_rvv
|
||||
|
||||
#define HAVE_CHUNKCOPY
|
||||
|
||||
/*
|
||||
* Assuming that the length is non-zero, and that `from` lags `out` by at least
|
||||
* sizeof chunk_t bytes, please see the comments in chunkset_tpl.h.
|
||||
*
|
||||
* We load/store a single chunk once in the `CHUNKCOPY`.
|
||||
* However, RISC-V glibc would enable RVV optimized memcpy at runtime by IFUNC,
|
||||
* such that, we prefer copy large memory size once to make good use of the the RVV advance.
|
||||
*
|
||||
* To be aligned to the other platforms, we didn't modify `CHUNKCOPY` method a lot,
|
||||
* but we still copy as much memory as possible for some conditions.
|
||||
*
|
||||
* case 1: out - from >= len (no overlap)
|
||||
* We can use memcpy to copy `len` size once
|
||||
* because the memory layout would be the same.
|
||||
*
|
||||
* case 2: overlap
|
||||
* We copy N chunks using memcpy at once, aiming to achieve our goal:
|
||||
* to copy as much memory as possible.
|
||||
*
|
||||
* After using a single memcpy to copy N chunks, we have to use series of
|
||||
* loadchunk and storechunk to ensure the result is correct.
|
||||
*/
|
||||
static inline uint8_t* CHUNKCOPY(uint8_t *out, uint8_t const *from, unsigned len) {
|
||||
Assert(len > 0, "chunkcopy should never have a length 0");
|
||||
int32_t align = ((len - 1) % sizeof(chunk_t)) + 1;
|
||||
memcpy(out, from, sizeof(chunk_t));
|
||||
out += align;
|
||||
from += align;
|
||||
len -= align;
|
||||
ptrdiff_t dist = out - from;
|
||||
if (dist >= len) {
|
||||
memcpy(out, from, len);
|
||||
out += len;
|
||||
from += len;
|
||||
return out;
|
||||
}
|
||||
if (dist >= sizeof(chunk_t)) {
|
||||
dist = (dist / sizeof(chunk_t)) * sizeof(chunk_t);
|
||||
memcpy(out, from, dist);
|
||||
out += dist;
|
||||
from += dist;
|
||||
len -= dist;
|
||||
}
|
||||
while (len > 0) {
|
||||
memcpy(out, from, sizeof(chunk_t));
|
||||
out += sizeof(chunk_t);
|
||||
from += sizeof(chunk_t);
|
||||
len -= sizeof(chunk_t);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
#include "chunkset_tpl.h"
|
||||
|
||||
#define INFLATE_FAST inflate_fast_rvv
|
||||
|
||||
#include "inffast_tpl.h"
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/* compare256_rvv.c - RVV version of compare256
|
||||
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
|
||||
* Contributed by Alex Chiang <alex.chiang@sifive.com>
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef RISCV_RVV
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "zutil_p.h"
|
||||
#include "deflate.h"
|
||||
#include "fallback_builtins.h"
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
static inline uint32_t compare256_rvv_static(const uint8_t *src0, const uint8_t *src1) {
|
||||
uint32_t len = 0;
|
||||
size_t vl;
|
||||
long found_diff;
|
||||
do {
|
||||
vl = __riscv_vsetvl_e8m4(256 - len);
|
||||
vuint8m4_t v_src0 = __riscv_vle8_v_u8m4(src0, vl);
|
||||
vuint8m4_t v_src1 = __riscv_vle8_v_u8m4(src1, vl);
|
||||
vbool2_t v_mask = __riscv_vmsne_vv_u8m4_b2(v_src0, v_src1, vl);
|
||||
found_diff = __riscv_vfirst_m_b2(v_mask, vl);
|
||||
if (found_diff >= 0)
|
||||
return len + (uint32_t)found_diff;
|
||||
src0 += vl, src1 += vl, len += vl;
|
||||
} while (len < 256);
|
||||
|
||||
return 256;
|
||||
}
|
||||
|
||||
Z_INTERNAL uint32_t compare256_rvv(const uint8_t *src0, const uint8_t *src1) {
|
||||
return compare256_rvv_static(src0, src1);
|
||||
}
|
||||
|
||||
#define LONGEST_MATCH longest_match_rvv
|
||||
#define COMPARE256 compare256_rvv_static
|
||||
|
||||
#include "match_tpl.h"
|
||||
|
||||
#define LONGEST_MATCH_SLOW
|
||||
#define LONGEST_MATCH longest_match_slow_rvv
|
||||
#define COMPARE256 compare256_rvv_static
|
||||
|
||||
#include "match_tpl.h"
|
||||
|
||||
#endif // RISCV_RVV
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#if defined(__linux__) && defined(HAVE_SYS_AUXV_H)
|
||||
# include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "riscv_features.h"
|
||||
|
||||
#define ISA_V_HWCAP (1 << ('v' - 'a'))
|
||||
|
||||
int Z_INTERNAL is_kernel_version_greater_or_equal_to_6_5() {
|
||||
struct utsname buffer;
|
||||
uname(&buffer);
|
||||
|
||||
int major, minor;
|
||||
if (sscanf(buffer.release, "%d.%d", &major, &minor) != 2) {
|
||||
// Something bad with uname()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (major > 6 || major == 6 && minor >= 5)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Z_INTERNAL riscv_check_features_compile_time(struct riscv_cpu_features *features) {
|
||||
#if defined(__riscv_v) && defined(__linux__)
|
||||
features->has_rvv = 1;
|
||||
#else
|
||||
features->has_rvv = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Z_INTERNAL riscv_check_features_runtime(struct riscv_cpu_features *features) {
|
||||
#if defined(__linux__) && defined(HAVE_SYS_AUXV_H)
|
||||
unsigned long hw_cap = getauxval(AT_HWCAP);
|
||||
#else
|
||||
unsigned long hw_cap = 0;
|
||||
#endif
|
||||
features->has_rvv = hw_cap & ISA_V_HWCAP;
|
||||
}
|
||||
|
||||
void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) {
|
||||
if (is_kernel_version_greater_or_equal_to_6_5())
|
||||
riscv_check_features_runtime(features);
|
||||
else
|
||||
riscv_check_features_compile_time(features);
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/* riscv_features.h -- check for riscv features.
|
||||
*
|
||||
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
|
||||
* Contributed by Alex Chiang <alex.chiang@sifive.com>
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef RISCV_FEATURES_H_
|
||||
#define RISCV_FEATURES_H_
|
||||
|
||||
struct riscv_cpu_features {
|
||||
int has_rvv;
|
||||
};
|
||||
|
||||
void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features);
|
||||
|
||||
#endif /* RISCV_FEATURES_H_ */
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/* riscv_functions.h -- RISCV implementations for arch-specific functions.
|
||||
*
|
||||
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
|
||||
* Contributed by Alex Chiang <alex.chiang@sifive.com>
|
||||
*
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifndef RISCV_FUNCTIONS_H_
|
||||
#define RISCV_FUNCTIONS_H_
|
||||
|
||||
#ifdef RISCV_RVV
|
||||
uint32_t adler32_rvv(uint32_t adler, const uint8_t *buf, size_t len);
|
||||
uint32_t adler32_fold_copy_rvv(uint32_t adler, uint8_t *dst, const uint8_t *src, size_t len);
|
||||
uint32_t chunksize_rvv(void);
|
||||
uint8_t* chunkmemset_safe_rvv(uint8_t *out, unsigned dist, unsigned len, unsigned left);
|
||||
uint32_t compare256_rvv(const uint8_t *src0, const uint8_t *src1);
|
||||
|
||||
uint32_t longest_match_rvv(deflate_state *const s, Pos cur_match);
|
||||
uint32_t longest_match_slow_rvv(deflate_state *const s, Pos cur_match);
|
||||
void slide_hash_rvv(deflate_state *s);
|
||||
void inflate_fast_rvv(PREFIX3(stream) *strm, uint32_t start);
|
||||
#endif
|
||||
|
||||
#ifdef DISABLE_RUNTIME_CPU_DETECTION
|
||||
// RISCV - RVV
|
||||
# if defined(RISCV_RVV) && defined(__riscv_v) && defined(__linux__)
|
||||
# undef native_adler32
|
||||
# define native_adler32 adler32_rvv
|
||||
# undef native_adler32_fold_copy
|
||||
# define native_adler32_fold_copy adler32_fold_copy_rvv
|
||||
# undef native_chunkmemset_safe
|
||||
# define native_chunkmemset_safe chunkmemset_safe_rvv
|
||||
# undef native_chunksize
|
||||
# define native_chunksize chunksize_rvv
|
||||
# undef native_compare256
|
||||
# define native_compare256 compare256_rvv
|
||||
# undef native_inflate_fast
|
||||
# define native_inflate_fast inflate_fast_rvv
|
||||
# undef native_longest_match
|
||||
# define native_longest_match longest_match_rvv
|
||||
# undef native_longest_match_slow
|
||||
# define native_longest_match_slow longest_match_slow_rvv
|
||||
# undef native_slide_hash
|
||||
# define native_slide_hash slide_hash_rvv
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* RISCV_FUNCTIONS_H_ */
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/* slide_hash_rvv.c - RVV version of slide_hash
|
||||
* Copyright (C) 2023 SiFive, Inc. All rights reserved.
|
||||
* Contributed by Alex Chiang <alex.chiang@sifive.com>
|
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/
|
||||
|
||||
#ifdef RISCV_RVV
|
||||
|
||||
#include <riscv_vector.h>
|
||||
|
||||
#include "zbuild.h"
|
||||
#include "deflate.h"
|
||||
|
||||
static inline void slide_hash_chain(Pos *table, uint32_t entries, uint16_t wsize) {
|
||||
size_t vl;
|
||||
while (entries > 0) {
|
||||
vl = __riscv_vsetvl_e16m4(entries);
|
||||
vuint16m4_t v_tab = __riscv_vle16_v_u16m4(table, vl);
|
||||
vuint16m4_t v_diff = __riscv_vssubu_vx_u16m4(v_tab, wsize, vl);
|
||||
__riscv_vse16_v_u16m4(table, v_diff, vl);
|
||||
table += vl, entries -= vl;
|
||||
}
|
||||
}
|
||||
|
||||
Z_INTERNAL void slide_hash_rvv(deflate_state *s) {
|
||||
uint16_t wsize = (uint16_t)s->w_size;
|
||||
|
||||
slide_hash_chain(s->head, HASH_SIZE, wsize);
|
||||
slide_hash_chain(s->prev, wsize, wsize);
|
||||
}
|
||||
|
||||
#endif // RISCV_RVV
|
||||
Reference in New Issue
Block a user