Skip to content

Commit fb14e22

Browse files
authored
Merge pull request #2962 from facebook/seqStore_off
Refactor offset+repcode sumtype
2 parents 4f63cb9 + ad7c9fc commit fb14e22

15 files changed

+349
-284
lines changed

lib/common/zstd_internal.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ extern "C" {
6767
#define ZSTD_OPT_NUM (1<<12)
6868

6969
#define ZSTD_REP_NUM 3 /* number of repcodes */
70-
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
7170
static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
7271

7372
#define KB *(1 <<10)
@@ -285,7 +284,7 @@ typedef enum {
285284
* Private declarations
286285
*********************************************/
287286
typedef struct seqDef_s {
288-
U32 offset; /* offset == rawOffset + ZSTD_REP_NUM, or equivalently, offCode + 1 */
287+
U32 offBase; /* offBase == Offset + ZSTD_REP_NUM, or repcode 1,2,3 */
289288
U16 litLength;
290289
U16 mlBase; /* mlBase == matchLength - MINMATCH */
291290
} seqDef;

lib/compress/zstd_compress.c

Lines changed: 109 additions & 91 deletions
Large diffs are not rendered by default.

lib/compress/zstd_compress_internal.h

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ size_t ZSTD_buildBlockEntropyStats(seqStore_t* seqStorePtr,
129129
*********************************/
130130

131131
typedef struct {
132-
U32 off; /* Offset code (offset + ZSTD_REP_MOVE) for the match */
132+
U32 off; /* Offset sumtype code for the match, using ZSTD_storeSeq() format */
133133
U32 len; /* Raw length of match */
134134
} ZSTD_match_t;
135135

@@ -497,31 +497,6 @@ MEM_STATIC U32 ZSTD_MLcode(U32 mlBase)
497497
return (mlBase > 127) ? ZSTD_highbit32(mlBase) + ML_deltaCode : ML_Code[mlBase];
498498
}
499499

500-
typedef struct repcodes_s {
501-
U32 rep[3];
502-
} repcodes_t;
503-
504-
MEM_STATIC repcodes_t ZSTD_updateRep(U32 const rep[3], U32 const offset, U32 const ll0)
505-
{
506-
repcodes_t newReps;
507-
if (offset >= ZSTD_REP_NUM) { /* full offset */
508-
newReps.rep[2] = rep[1];
509-
newReps.rep[1] = rep[0];
510-
newReps.rep[0] = offset - ZSTD_REP_MOVE;
511-
} else { /* repcode */
512-
U32 const repCode = offset + ll0;
513-
if (repCode > 0) { /* note : if repCode==0, no change */
514-
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
515-
newReps.rep[2] = (repCode >= 2) ? rep[1] : rep[2];
516-
newReps.rep[1] = rep[0];
517-
newReps.rep[0] = currentOffset;
518-
} else { /* repCode == 0 */
519-
ZSTD_memcpy(&newReps, rep, sizeof(newReps));
520-
}
521-
}
522-
return newReps;
523-
}
524-
525500
/* ZSTD_cParam_withinBounds:
526501
* @return 1 if value is within cParam bounds,
527502
* 0 otherwise */
@@ -590,7 +565,9 @@ MEM_STATIC int ZSTD_literalsCompressionIsDisabled(const ZSTD_CCtx_params* cctxPa
590565
* Only called when the sequence ends past ilimit_w, so it only needs to be optimized for single
591566
* large copies.
592567
*/
593-
static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w) {
568+
static void
569+
ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const iend, BYTE const* ilimit_w)
570+
{
594571
assert(iend > ilimit_w);
595572
if (ip <= ilimit_w) {
596573
ZSTD_wildcopy(op, ip, ilimit_w - ip, ZSTD_no_overlap);
@@ -600,14 +577,30 @@ static void ZSTD_safecopyLiterals(BYTE* op, BYTE const* ip, BYTE const* const ie
600577
while (ip < iend) *op++ = *ip++;
601578
}
602579

580+
#define ZSTD_REP_MOVE (ZSTD_REP_NUM-1)
581+
#define STORE_REPCODE_1 STORE_REPCODE(1)
582+
#define STORE_REPCODE_2 STORE_REPCODE(2)
583+
#define STORE_REPCODE_3 STORE_REPCODE(3)
584+
#define STORE_REPCODE(r) (assert((r)>=1), assert((r)<=3), (r)-1)
585+
#define STORE_OFFSET(o) (assert((o)>0), o + ZSTD_REP_MOVE)
586+
#define STORED_IS_OFFSET(o) ((o) > ZSTD_REP_MOVE)
587+
#define STORED_IS_REPCODE(o) ((o) <= ZSTD_REP_MOVE)
588+
#define STORED_OFFSET(o) (assert(STORED_IS_OFFSET(o)), (o)-ZSTD_REP_MOVE)
589+
#define STORED_REPCODE(o) (assert(STORED_IS_REPCODE(o)), (o)+1) /* returns ID 1,2,3 */
590+
#define STORED_TO_OFFBASE(o) ((o)+1)
591+
#define OFFBASE_TO_STORED(o) ((o)-1)
592+
603593
/*! ZSTD_storeSeq() :
604594
* Store a sequence (litlen, litPtr, offCode and matchLength) into seqStore_t.
605-
* `offCode` : distance to match + ZSTD_REP_MOVE (values <= ZSTD_REP_MOVE are repCodes).
595+
* @offBase_minus1 : Users should use employ macros STORE_REPCODE_X and STORE_OFFSET().
606596
* @matchLength : must be >= MINMATCH
607597
* Allowed to overread literals up to litLimit.
608598
*/
609-
HINT_INLINE UNUSED_ATTR
610-
void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* literals, const BYTE* litLimit, U32 offCode, size_t matchLength)
599+
HINT_INLINE UNUSED_ATTR void
600+
ZSTD_storeSeq(seqStore_t* seqStorePtr,
601+
size_t litLength, const BYTE* literals, const BYTE* litLimit,
602+
U32 offBase_minus1,
603+
size_t matchLength)
611604
{
612605
BYTE const* const litLimit_w = litLimit - WILDCOPY_OVERLENGTH;
613606
BYTE const* const litEnd = literals + litLength;
@@ -616,7 +609,7 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
616609
if (g_start==NULL) g_start = (const BYTE*)literals; /* note : index only works for compression within a single segment */
617610
{ U32 const pos = (U32)((const BYTE*)literals - g_start);
618611
DEBUGLOG(6, "Cpos%7u :%3u literals, match%4u bytes at offCode%7u",
619-
pos, (U32)litLength, (U32)matchLength, (U32)offCode);
612+
pos, (U32)litLength, (U32)matchLength, (U32)offBase_minus1);
620613
}
621614
#endif
622615
assert((size_t)(seqStorePtr->sequences - seqStorePtr->sequencesStart) < seqStorePtr->maxNbSeq);
@@ -647,7 +640,7 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
647640
seqStorePtr->sequences[0].litLength = (U16)litLength;
648641

649642
/* match offset */
650-
seqStorePtr->sequences[0].offset = offCode + 1;
643+
seqStorePtr->sequences[0].offBase = STORED_TO_OFFBASE(offBase_minus1);
651644

652645
/* match Length */
653646
assert(matchLength >= MINMATCH);
@@ -663,6 +656,43 @@ void ZSTD_storeSeq(seqStore_t* seqStorePtr, size_t litLength, const BYTE* litera
663656
seqStorePtr->sequences++;
664657
}
665658

659+
/* ZSTD_updateRep() :
660+
* updates in-place @rep (array of repeat offsets)
661+
* @offBase_minus1 : sum-type, with same numeric representation as ZSTD_storeSeq()
662+
*/
663+
MEM_STATIC void
664+
ZSTD_updateRep(U32 rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
665+
{
666+
if (STORED_IS_OFFSET(offBase_minus1)) { /* full offset */
667+
rep[2] = rep[1];
668+
rep[1] = rep[0];
669+
rep[0] = STORED_OFFSET(offBase_minus1);
670+
} else { /* repcode */
671+
U32 const repCode = STORED_REPCODE(offBase_minus1) - 1 + ll0;
672+
if (repCode > 0) { /* note : if repCode==0, no change */
673+
U32 const currentOffset = (repCode==ZSTD_REP_NUM) ? (rep[0] - 1) : rep[repCode];
674+
rep[2] = (repCode >= 2) ? rep[1] : rep[2];
675+
rep[1] = rep[0];
676+
rep[0] = currentOffset;
677+
} else { /* repCode == 0 */
678+
/* nothing to do */
679+
}
680+
}
681+
}
682+
683+
typedef struct repcodes_s {
684+
U32 rep[3];
685+
} repcodes_t;
686+
687+
MEM_STATIC repcodes_t
688+
ZSTD_newRep(U32 const rep[ZSTD_REP_NUM], U32 const offBase_minus1, U32 const ll0)
689+
{
690+
repcodes_t newReps;
691+
ZSTD_memcpy(&newReps, rep, sizeof(newReps));
692+
ZSTD_updateRep(newReps.rep, offBase_minus1, ll0);
693+
return newReps;
694+
}
695+
666696

667697
/*-*************************************
668698
* Match length counter

lib/compress/zstd_compress_sequences.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -319,13 +319,13 @@ ZSTD_encodeSequences_body(
319319
U32 const ofBits = ofCodeTable[nbSeq-1];
320320
unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
321321
if (extraBits) {
322-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, extraBits);
322+
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, extraBits);
323323
BIT_flushBits(&blockStream);
324324
}
325-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset >> extraBits,
325+
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase >> extraBits,
326326
ofBits - extraBits);
327327
} else {
328-
BIT_addBits(&blockStream, sequences[nbSeq-1].offset, ofCodeTable[nbSeq-1]);
328+
BIT_addBits(&blockStream, sequences[nbSeq-1].offBase, ofCodeTable[nbSeq-1]);
329329
}
330330
BIT_flushBits(&blockStream);
331331

@@ -340,7 +340,7 @@ ZSTD_encodeSequences_body(
340340
DEBUGLOG(6, "encoding: litlen:%2u - matchlen:%2u - offCode:%7u",
341341
(unsigned)sequences[n].litLength,
342342
(unsigned)sequences[n].mlBase + MINMATCH,
343-
(unsigned)sequences[n].offset);
343+
(unsigned)sequences[n].offBase);
344344
/* 32b*/ /* 64b*/
345345
/* (7)*/ /* (7)*/
346346
FSE_encodeSymbol(&blockStream, &stateOffsetBits, ofCode); /* 15 */ /* 15 */
@@ -356,13 +356,13 @@ ZSTD_encodeSequences_body(
356356
if (longOffsets) {
357357
unsigned const extraBits = ofBits - MIN(ofBits, STREAM_ACCUMULATOR_MIN-1);
358358
if (extraBits) {
359-
BIT_addBits(&blockStream, sequences[n].offset, extraBits);
359+
BIT_addBits(&blockStream, sequences[n].offBase, extraBits);
360360
BIT_flushBits(&blockStream); /* (7)*/
361361
}
362-
BIT_addBits(&blockStream, sequences[n].offset >> extraBits,
362+
BIT_addBits(&blockStream, sequences[n].offBase >> extraBits,
363363
ofBits - extraBits); /* 31 */
364364
} else {
365-
BIT_addBits(&blockStream, sequences[n].offset, ofBits); /* 31 */
365+
BIT_addBits(&blockStream, sequences[n].offBase, ofBits); /* 31 */
366366
}
367367
BIT_flushBits(&blockStream); /* (7)*/
368368
DEBUGLOG(7, "remaining space : %i", (int)(blockStream.endPtr - blockStream.ptr));

lib/compress/zstd_compress_superblock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ static size_t ZSTD_compressSubBlock_multi(const seqStore_t* seqStorePtr,
539539
repcodes_t rep;
540540
ZSTD_memcpy(&rep, prevCBlock->rep, sizeof(rep));
541541
for (seq = sstart; seq < sp; ++seq) {
542-
rep = ZSTD_updateRep(rep.rep, seq->offset - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
542+
ZSTD_updateRep(rep.rep, seq->offBase - 1, ZSTD_getSequenceLength(seqStorePtr, seq).litLength == 0);
543543
}
544544
ZSTD_memcpy(nextCBlock->rep, &rep, sizeof(rep));
545545
}

lib/compress/zstd_double_fast.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic(
131131
if ((offset_1 > 0) & (MEM_read32(ip+1-offset_1) == MEM_read32(ip+1))) {
132132
mLength = ZSTD_count(ip+1+4, ip+1+4-offset_1, iend) + 4;
133133
ip++;
134-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength);
134+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
135135
goto _match_stored;
136136
}
137137

@@ -217,7 +217,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic(
217217
hashLong[hl1] = (U32)(ip1 - base);
218218
}
219219

220-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength);
220+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
221221

222222
_match_stored:
223223
/* match found */
@@ -243,7 +243,7 @@ size_t ZSTD_compressBlock_doubleFast_noDict_generic(
243243
U32 const tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; /* swap offset_2 <=> offset_1 */
244244
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = (U32)(ip-base);
245245
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = (U32)(ip-base);
246-
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength);
246+
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, rLength);
247247
ip += rLength;
248248
anchor = ip;
249249
continue; /* faster when present ... (?) */
@@ -328,7 +328,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
328328
const BYTE* repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend;
329329
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixLowest) + 4;
330330
ip++;
331-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength);
331+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
332332
goto _match_stored;
333333
}
334334

@@ -419,7 +419,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
419419
offset_2 = offset_1;
420420
offset_1 = offset;
421421

422-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength);
422+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
423423

424424
_match_stored:
425425
/* match found */
@@ -448,7 +448,7 @@ size_t ZSTD_compressBlock_doubleFast_dictMatchState_generic(
448448
const BYTE* const repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend;
449449
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixLowest) + 4;
450450
U32 tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
451-
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2);
451+
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
452452
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
453453
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
454454
ip += repLength2;
@@ -585,7 +585,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
585585
const BYTE* repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend;
586586
mLength = ZSTD_count_2segments(ip+1+4, repMatch+4, iend, repMatchEnd, prefixStart) + 4;
587587
ip++;
588-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, 0, mLength);
588+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_REPCODE_1, mLength);
589589
} else {
590590
if ((matchLongIndex > dictStartIndex) && (MEM_read64(matchLong) == MEM_read64(ip))) {
591591
const BYTE* const matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend;
@@ -596,7 +596,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
596596
while (((ip>anchor) & (matchLong>lowMatchPtr)) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } /* catch up */
597597
offset_2 = offset_1;
598598
offset_1 = offset;
599-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength);
599+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
600600

601601
} else if ((matchIndex > dictStartIndex) && (MEM_read32(match) == MEM_read32(ip))) {
602602
size_t const h3 = ZSTD_hashPtr(ip+1, hBitsL, 8);
@@ -621,7 +621,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
621621
}
622622
offset_2 = offset_1;
623623
offset_1 = offset;
624-
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, offset + ZSTD_REP_MOVE, mLength);
624+
ZSTD_storeSeq(seqStore, (size_t)(ip-anchor), anchor, iend, STORE_OFFSET(offset), mLength);
625625

626626
} else {
627627
ip += ((ip-anchor) >> kSearchStrength) + 1;
@@ -653,7 +653,7 @@ static size_t ZSTD_compressBlock_doubleFast_extDict_generic(
653653
const BYTE* const repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend;
654654
size_t const repLength2 = ZSTD_count_2segments(ip+4, repMatch2+4, iend, repEnd2, prefixStart) + 4;
655655
U32 const tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; /* swap offset_2 <=> offset_1 */
656-
ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2);
656+
ZSTD_storeSeq(seqStore, 0, anchor, iend, STORE_REPCODE_1, repLength2);
657657
hashSmall[ZSTD_hashPtr(ip, hBitsS, mls)] = current2;
658658
hashLong[ZSTD_hashPtr(ip, hBitsL, 8)] = current2;
659659
ip += repLength2;

0 commit comments

Comments
 (0)