feat(compress): move match table reduction to Rust
Port the 16-cell match-table reduction leaf while preserving the window-index threshold, wrapping subtraction, and btlazy2 unsorted marker. Keep ZSTD_reduceIndex and its strategy-specific table selection in C behind the narrow Rust ABI. Test Plan: cargo test --manifest-path rust/Cargo.toml --no-default-features --features compression (180 passed); root clippy, bench clippy, and test clippy; make -B -C lib -j2 lib; make -B -C tests -j2 test-zstream (84 named tests plus 6,845 and 9,628 fuzz cases passed).
This commit is contained in:
@@ -52,6 +52,8 @@ size_t ZSTD_compressStream2_c(ZSTD_CCtx* cctx,
|
||||
ZSTD_EndDirective endOp);
|
||||
int ZSTD_rust_simpleCompress2Level(const void* cctx);
|
||||
int ZSTD_rust_simpleCompressStream2Level(const void* cctx);
|
||||
void ZSTD_rust_reduceTable(U32* table, U32 size, U32 reducerValue,
|
||||
int preserveMark);
|
||||
|
||||
/* Context-free compression-parameter selection and sizing leaves live in
|
||||
* Rust (rust/src/zstd_compress_params.rs). This file retains
|
||||
@@ -2076,63 +2078,20 @@ size_t ZSTD_copyCCtx(ZSTD_CCtx* dstCCtx, const ZSTD_CCtx* srcCCtx, unsigned long
|
||||
}
|
||||
|
||||
|
||||
#define ZSTD_ROWSIZE 16
|
||||
/*! ZSTD_reduceTable() :
|
||||
* reduce table indexes by `reducerValue`, or squash to zero.
|
||||
* PreserveMark preserves "unsorted mark" for btlazy2 strategy.
|
||||
* It must be set to a clear 0/1 value, to remove branch during inlining.
|
||||
* Presume table size is a multiple of ZSTD_ROWSIZE
|
||||
* Presume table size is a multiple of 16 cells
|
||||
* to help auto-vectorization */
|
||||
FORCE_INLINE_TEMPLATE void
|
||||
ZSTD_reduceTable_internal (U32* const table, U32 const size, U32 const reducerValue, int const preserveMark)
|
||||
{
|
||||
int const nbRows = (int)size / ZSTD_ROWSIZE;
|
||||
int cellNb = 0;
|
||||
int rowNb;
|
||||
/* Protect special index values < ZSTD_WINDOW_START_INDEX. */
|
||||
U32 const reducerThreshold = reducerValue + ZSTD_WINDOW_START_INDEX;
|
||||
assert((size & (ZSTD_ROWSIZE-1)) == 0); /* multiple of ZSTD_ROWSIZE */
|
||||
assert(size < (1U<<31)); /* can be cast to int */
|
||||
|
||||
#if ZSTD_MEMORY_SANITIZER && !defined (ZSTD_MSAN_DONT_POISON_WORKSPACE)
|
||||
/* To validate that the table reuse logic is sound, and that we don't
|
||||
* access table space that we haven't cleaned, we re-"poison" the table
|
||||
* space every time we mark it dirty.
|
||||
*
|
||||
* This function however is intended to operate on those dirty tables and
|
||||
* re-clean them. So when this function is used correctly, we can unpoison
|
||||
* the memory it operated on. This introduces a blind spot though, since
|
||||
* if we now try to operate on __actually__ poisoned memory, we will not
|
||||
* detect that. */
|
||||
__msan_unpoison(table, size * sizeof(U32));
|
||||
#endif
|
||||
|
||||
for (rowNb=0 ; rowNb < nbRows ; rowNb++) {
|
||||
int column;
|
||||
for (column=0; column<ZSTD_ROWSIZE; column++) {
|
||||
U32 newVal;
|
||||
if (preserveMark && table[cellNb] == ZSTD_DUBT_UNSORTED_MARK) {
|
||||
/* This write is pointless, but is required(?) for the compiler
|
||||
* to auto-vectorize the loop. */
|
||||
newVal = ZSTD_DUBT_UNSORTED_MARK;
|
||||
} else if (table[cellNb] < reducerThreshold) {
|
||||
newVal = 0;
|
||||
} else {
|
||||
newVal = table[cellNb] - reducerValue;
|
||||
}
|
||||
table[cellNb] = newVal;
|
||||
cellNb++;
|
||||
} }
|
||||
}
|
||||
|
||||
static void ZSTD_reduceTable(U32* const table, U32 const size, U32 const reducerValue)
|
||||
{
|
||||
ZSTD_reduceTable_internal(table, size, reducerValue, 0);
|
||||
ZSTD_rust_reduceTable(table, size, reducerValue, 0);
|
||||
}
|
||||
|
||||
static void ZSTD_reduceTable_btlazy2(U32* const table, U32 const size, U32 const reducerValue)
|
||||
{
|
||||
ZSTD_reduceTable_internal(table, size, reducerValue, 1);
|
||||
ZSTD_rust_reduceTable(table, size, reducerValue, 1);
|
||||
}
|
||||
|
||||
/*! ZSTD_reduceIndex() :
|
||||
|
||||
Reference in New Issue
Block a user