Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

decompress: add -DZSTD_DISABLE_FAST_C_LOOP to disable fast C loops #3778

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion doc/zstd_manual.html
Original file line number Diff line number Diff line change
Expand Up @@ -513,14 +513,18 @@ <h3>Decompression context</h3><pre> When decompressing many times,
* ZSTD_d_forceIgnoreChecksum
* ZSTD_d_refMultipleDDicts
* ZSTD_d_disableHuffmanAssembly
* ZSTD_d_maxBlockSize
* ZSTD_d_disableFastCLoops
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
ZSTD_d_experimentalParam1=1000,
ZSTD_d_experimentalParam2=1001,
ZSTD_d_experimentalParam3=1002,
ZSTD_d_experimentalParam4=1003,
ZSTD_d_experimentalParam5=1004
ZSTD_d_experimentalParam5=1004,
ZSTD_d_experimentalParam6=1005,
ZSTD_d_experimentalParam7=1006,

} ZSTD_dParameter;
</b></pre><BR>
Expand Down
9 changes: 9 additions & 0 deletions lib/common/portability_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@
# define ZSTD_ENABLE_ASM_X86_64_BMI2 0
#endif

/**
*
*/
#if !defined(ZSTD_DISABLE_FAST_C_LOOP)
# define ZSTD_ENABLE_FAST_C_LOOP 1
#else
# define ZSTD_ENABLE_FAST_C_LOOP 0
#endif

/*
* For x86 ELF targets, add .note.gnu.property section for Intel CET in
* assembly sources when CET is enabled.
Expand Down
21 changes: 16 additions & 5 deletions lib/decompress/huf_decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ HUF_ASM_DECL void HUF_decompress4X1_usingDTable_internal_fast_asm_loop(HUF_Decom

#endif

#if ZSTD_ENABLE_FAST_C_LOOP
static HUF_FAST_BMI2_ATTRS
void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)
{
Expand Down Expand Up @@ -782,6 +783,7 @@ void HUF_decompress4X1_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));
ZSTD_memcpy(&args->op, &op, sizeof(op));
}
#endif

/**
* @returns @p dstSize on success (>= 6)
Expand Down Expand Up @@ -847,7 +849,11 @@ static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize,
size_t cSrcSize, HUF_DTable const* DTable, int flags)
{
HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X1_usingDTable_internal_default;
HUF_DecompressFastLoopFn loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;
HUF_DecompressFastLoopFn loopFn = NULL;

#if ZSTD_ENABLE_FAST_C_LOOP
loopFn = HUF_decompress4X1_usingDTable_internal_fast_c_loop;
#endif

#if DYNAMIC_BMI2
if (flags & HUF_flags_bmi2) {
Expand All @@ -868,7 +874,7 @@ static size_t HUF_decompress4X1_usingDTable_internal(void* dst, size_t dstSize,
}
#endif

if (!(flags & HUF_flags_disableFast)) {
if (loopFn && !(flags & HUF_flags_disableFast)) {
size_t const ret = HUF_decompress4X1_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
if (ret != 0)
return ret;
Expand Down Expand Up @@ -1464,6 +1470,7 @@ HUF_ASM_DECL void HUF_decompress4X2_usingDTable_internal_fast_asm_loop(HUF_Decom

#endif

#if ZSTD_ENABLE_FAST_C_LOOP
static HUF_FAST_BMI2_ATTRS
void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs* args)
{
Expand Down Expand Up @@ -1602,7 +1609,7 @@ void HUF_decompress4X2_usingDTable_internal_fast_c_loop(HUF_DecompressFastArgs*
ZSTD_memcpy((void*)(&args->ip), &ip, sizeof(ip));
ZSTD_memcpy(&args->op, &op, sizeof(op));
}

#endif

static HUF_FAST_BMI2_ATTRS size_t
HUF_decompress4X2_usingDTable_internal_fast(
Expand Down Expand Up @@ -1658,7 +1665,11 @@ static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize,
size_t cSrcSize, HUF_DTable const* DTable, int flags)
{
HUF_DecompressUsingDTableFn fallbackFn = HUF_decompress4X2_usingDTable_internal_default;
HUF_DecompressFastLoopFn loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;
HUF_DecompressFastLoopFn loopFn = NULL;

#if ZSTD_ENABLE_FAST_C_LOOP
loopFn = HUF_decompress4X2_usingDTable_internal_fast_c_loop;
#endif

#if DYNAMIC_BMI2
if (flags & HUF_flags_bmi2) {
Expand All @@ -1679,7 +1690,7 @@ static size_t HUF_decompress4X2_usingDTable_internal(void* dst, size_t dstSize,
}
#endif

if (!(flags & HUF_flags_disableFast)) {
if (loopFn && !(flags & HUF_flags_disableFast)) {
size_t const ret = HUF_decompress4X2_usingDTable_internal_fast(dst, dstSize, cSrc, cSrcSize, DTable, loopFn);
if (ret != 0)
return ret;
Expand Down
9 changes: 9 additions & 0 deletions lib/decompress/zstd_decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ static void ZSTD_DCtx_resetParameters(ZSTD_DCtx* dctx)
dctx->forceIgnoreChecksum = ZSTD_d_validateChecksum;
dctx->refMultipleDDicts = ZSTD_rmd_refSingleDDict;
dctx->disableHufAsm = 0;
dctx->disableHufFastCLoops = 0;
dctx->maxBlockSizeParam = 0;
}

Expand Down Expand Up @@ -1831,6 +1832,7 @@ ZSTD_bounds ZSTD_dParam_getBounds(ZSTD_dParameter dParam)
bounds.upperBound = (int)ZSTD_rmd_refMultipleDDicts;
return bounds;
case ZSTD_d_disableHuffmanAssembly:
case ZSTD_d_disableHuffmanFastCLoops:
bounds.lowerBound = 0;
bounds.upperBound = 1;
return bounds;
Expand Down Expand Up @@ -1882,6 +1884,9 @@ size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParameter param, int* value
case ZSTD_d_disableHuffmanAssembly:
*value = (int)dctx->disableHufAsm;
return 0;
case ZSTD_d_disableHuffmanFastCLoops:
*value = (int)dctx->disableHufFastCLoops;
return 0;
case ZSTD_d_maxBlockSize:
*value = dctx->maxBlockSizeParam;
return 0;
Expand Down Expand Up @@ -1922,6 +1927,10 @@ size_t ZSTD_DCtx_setParameter(ZSTD_DCtx* dctx, ZSTD_dParameter dParam, int value
CHECK_DBOUNDS(ZSTD_d_disableHuffmanAssembly, value);
dctx->disableHufAsm = value != 0;
return 0;
case ZSTD_d_disableHuffmanFastCLoops:
CHECK_DBOUNDS(ZSTD_d_disableHuffmanFastCLoops, value);
dctx->disableHufFastCLoops = value != 0;
return 0;
case ZSTD_d_maxBlockSize:
if (value != 0) CHECK_DBOUNDS(ZSTD_d_maxBlockSize, value);
dctx->maxBlockSizeParam = value;
Expand Down
3 changes: 2 additions & 1 deletion lib/decompress/zstd_decompress_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ static size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx* dctx,
size_t expectedWriteSize = MIN(blockSizeMax, dstCapacity);
int const flags = 0
| (ZSTD_DCtx_get_bmi2(dctx) ? HUF_flags_bmi2 : 0)
| (dctx->disableHufAsm ? HUF_flags_disableAsm : 0);
| (dctx->disableHufAsm ? HUF_flags_disableAsm : 0)
| (dctx->disableHufFastCLoops ? HUF_flags_disableFast : 0);
switch(lhlCode)
{
case 0: case 1: default: /* note : default is impossible, since lhlCode into [0..3] */
Expand Down
1 change: 1 addition & 0 deletions lib/decompress/zstd_decompress_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ struct ZSTD_DCtx_s
ZSTD_DDictHashSet* ddictSet; /* Hash set for multiple ddicts */
ZSTD_refMultipleDDicts_e refMultipleDDicts; /* User specified: if == 1, will allow references to multiple DDicts. Default == 0 (disabled) */
int disableHufAsm;
int disableHufFastCLoops;
int maxBlockSizeParam;

/* streaming */
Expand Down
16 changes: 15 additions & 1 deletion lib/zstd.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ typedef enum {
* ZSTD_d_refMultipleDDicts
* ZSTD_d_disableHuffmanAssembly
* ZSTD_d_maxBlockSize
* ZSTD_d_disableHuffmanFastCLoops
* Because they are not stable, it's necessary to define ZSTD_STATIC_LINKING_ONLY to access them.
* note : never ever use experimentalParam? names directly
*/
Expand All @@ -627,7 +628,8 @@ typedef enum {
ZSTD_d_experimentalParam3=1002,
ZSTD_d_experimentalParam4=1003,
ZSTD_d_experimentalParam5=1004,
ZSTD_d_experimentalParam6=1005
ZSTD_d_experimentalParam6=1005,
ZSTD_d_experimentalParam7=1006

} ZSTD_dParameter;

Expand Down Expand Up @@ -2455,6 +2457,18 @@ ZSTDLIB_STATIC_API size_t ZSTD_DCtx_getParameter(ZSTD_DCtx* dctx, ZSTD_dParamete
#define ZSTD_d_maxBlockSize ZSTD_d_experimentalParam6


/* ZSTD_d_disableHuffmanFastCLoops
* Set to 1 to disable the generic C fast compression loops.
* The default value is 0, which allows zstd to use the generic C fast
* compression loops.
*
* This parameter can be used to disable the generic C fast compression loops
* at runtime. If you want to disable them at compile time you can define the
* macro ZSTD_DISABLE_FAST_C_LOOP.
*/
#define ZSTD_d_disableHuffmanFastCLoops ZSTD_d_experimentalParam7


/*! ZSTD_DCtx_setFormat() :
* This function is REDUNDANT. Prefer ZSTD_DCtx_setParameter().
* Instruct the decoder context about what kind of data to decode next.
Expand Down
11 changes: 11 additions & 0 deletions tests/fuzzer.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,17 @@ static int basicUnitTests(U32 const seed, double compressibility)
}
DISPLAYLEVEL(3, "OK \n");

DISPLAYLEVEL(3, "test%3i : decompress %u bytes with fast C Loops disabled : ", testNb++, (unsigned)CNBuffSize);
{
ZSTD_DCtx* dctx = ZSTD_createDCtx();
size_t r;
CHECK_Z(ZSTD_DCtx_setParameter(dctx, ZSTD_d_disableHuffmanFastCLoops, 1));
r = ZSTD_decompress(decodedBuffer, CNBuffSize, compressedBuffer, cSize);
if (r != CNBuffSize || memcmp(decodedBuffer, CNBuffer, CNBuffSize)) goto _output_error;
ZSTD_freeDCtx(dctx);
}
DISPLAYLEVEL(3, "OK \n");

DISPLAYLEVEL(3, "test%3i : check decompressed result : ", testNb++);
{ size_t u;
for (u=0; u<CNBuffSize; u++) {
Expand Down
6 changes: 6 additions & 0 deletions tests/zstreamtest.c
Original file line number Diff line number Diff line change
Expand Up @@ -3044,6 +3044,9 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
if (FUZ_rand(&lseed) & 1) {
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));
}
if (FUZ_rand(&lseed) & 1) {
CHECK_Z(ZSTD_DCtx_setParameter(zd, ZSTD_d_disableHuffmanFastCLoops, FUZ_rand(&lseed) & 1));
}
if (FUZ_rand(&lseed) & 1) {
int maxBlockSize;
CHECK_Z(ZSTD_CCtx_getParameter(zc, ZSTD_c_maxBlockSize, &maxBlockSize));
Expand Down Expand Up @@ -3100,6 +3103,9 @@ static int fuzzerTests_newAPI(U32 seed, int nbTests, int startTest,
if (FUZ_rand(&lseed) & 1) {
CHECK_Z(ZSTD_DCtx_setParameter(zd_noise, ZSTD_d_disableHuffmanAssembly, FUZ_rand(&lseed) & 1));
}
if (FUZ_rand(&lseed) & 1) {
CHECK_Z(ZSTD_DCtx_setParameter(zd_noise, ZSTD_d_disableHuffmanFastCLoops, FUZ_rand(&lseed) & 1));
}
{ ZSTD_inBuffer inBuff = { cBuffer, cSize, 0 };
ZSTD_outBuffer outBuff= { dstBuffer, dstBufferSize, 0 };
while (outBuff.pos < dstBufferSize) {
Expand Down
Loading