xref: /linux-6.15/lib/zstd/common/zstd_internal.h (revision 65d1f550)
1*65d1f550SNick Terrell /* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
2e0c1b49fSNick Terrell /*
3*65d1f550SNick Terrell  * Copyright (c) Meta Platforms, Inc. and affiliates.
4e0c1b49fSNick Terrell  * All rights reserved.
5e0c1b49fSNick Terrell  *
6e0c1b49fSNick Terrell  * This source code is licensed under both the BSD-style license (found in the
7e0c1b49fSNick Terrell  * LICENSE file in the root directory of this source tree) and the GPLv2 (found
8e0c1b49fSNick Terrell  * in the COPYING file in the root directory of this source tree).
9e0c1b49fSNick Terrell  * You may select, at your option, one of the above-listed licenses.
10e0c1b49fSNick Terrell  */
11e0c1b49fSNick Terrell 
12e0c1b49fSNick Terrell #ifndef ZSTD_CCOMMON_H_MODULE
13e0c1b49fSNick Terrell #define ZSTD_CCOMMON_H_MODULE
14e0c1b49fSNick Terrell 
15e0c1b49fSNick Terrell /* this module contains definitions which must be identical
16e0c1b49fSNick Terrell  * across compression, decompression and dictBuilder.
17e0c1b49fSNick Terrell  * It also contains a few functions useful to at least 2 of them
18e0c1b49fSNick Terrell  * and which benefit from being inlined */
19e0c1b49fSNick Terrell 
20e0c1b49fSNick Terrell /*-*************************************
21e0c1b49fSNick Terrell *  Dependencies
22e0c1b49fSNick Terrell ***************************************/
23e0c1b49fSNick Terrell #include "compiler.h"
242aa14b1aSNick Terrell #include "cpu.h"
25e0c1b49fSNick Terrell #include "mem.h"
26e0c1b49fSNick Terrell #include "debug.h"                 /* assert, DEBUGLOG, RAWLOG, g_debuglevel */
27e0c1b49fSNick Terrell #include "error_private.h"
28e0c1b49fSNick Terrell #define ZSTD_STATIC_LINKING_ONLY
29e0c1b49fSNick Terrell #include <linux/zstd.h>
30e0c1b49fSNick Terrell #define FSE_STATIC_LINKING_ONLY
31e0c1b49fSNick Terrell #include "fse.h"
32e0c1b49fSNick Terrell #include "huf.h"
33e0c1b49fSNick Terrell #include <linux/xxhash.h>                /* XXH_reset, update, digest */
34e0c1b49fSNick Terrell #define ZSTD_TRACE 0
35e0c1b49fSNick Terrell 
36e0c1b49fSNick Terrell /* ---- static assert (debug) --- */
37e0c1b49fSNick Terrell #define ZSTD_STATIC_ASSERT(c) DEBUG_STATIC_ASSERT(c)
38e0c1b49fSNick Terrell #define ZSTD_isError ERR_isError   /* for inlining */
39e0c1b49fSNick Terrell #define FSE_isError  ERR_isError
40e0c1b49fSNick Terrell #define HUF_isError  ERR_isError
41e0c1b49fSNick Terrell 
42e0c1b49fSNick Terrell 
43e0c1b49fSNick Terrell /*-*************************************
44e0c1b49fSNick Terrell *  shared macros
45e0c1b49fSNick Terrell ***************************************/
46e0c1b49fSNick Terrell #undef MIN
47e0c1b49fSNick Terrell #undef MAX
48e0c1b49fSNick Terrell #define MIN(a,b) ((a)<(b) ? (a) : (b))
49e0c1b49fSNick Terrell #define MAX(a,b) ((a)>(b) ? (a) : (b))
502aa14b1aSNick Terrell #define BOUNDED(min,val,max) (MAX(min,MIN(val,max)))
51e0c1b49fSNick Terrell 
52e0c1b49fSNick Terrell 
53e0c1b49fSNick Terrell /*-*************************************
54e0c1b49fSNick Terrell *  Common constants
55e0c1b49fSNick Terrell ***************************************/
56e0c1b49fSNick Terrell #define ZSTD_OPT_NUM    (1<<12)
57e0c1b49fSNick Terrell 
58e0c1b49fSNick Terrell #define ZSTD_REP_NUM      3                 /* number of repcodes */
59e0c1b49fSNick Terrell static UNUSED_ATTR const U32 repStartValue[ZSTD_REP_NUM] = { 1, 4, 8 };
60e0c1b49fSNick Terrell 
61e0c1b49fSNick Terrell #define KB *(1 <<10)
62e0c1b49fSNick Terrell #define MB *(1 <<20)
63e0c1b49fSNick Terrell #define GB *(1U<<30)
64e0c1b49fSNick Terrell 
65e0c1b49fSNick Terrell #define BIT7 128
66e0c1b49fSNick Terrell #define BIT6  64
67e0c1b49fSNick Terrell #define BIT5  32
68e0c1b49fSNick Terrell #define BIT4  16
69e0c1b49fSNick Terrell #define BIT1   2
70e0c1b49fSNick Terrell #define BIT0   1
71e0c1b49fSNick Terrell 
72e0c1b49fSNick Terrell #define ZSTD_WINDOWLOG_ABSOLUTEMIN 10
73e0c1b49fSNick Terrell static UNUSED_ATTR const size_t ZSTD_fcs_fieldSize[4] = { 0, 2, 4, 8 };
74e0c1b49fSNick Terrell static UNUSED_ATTR const size_t ZSTD_did_fieldSize[4] = { 0, 1, 2, 4 };
75e0c1b49fSNick Terrell 
76e0c1b49fSNick Terrell #define ZSTD_FRAMEIDSIZE 4   /* magic number size */
77e0c1b49fSNick Terrell 
78e0c1b49fSNick Terrell #define ZSTD_BLOCKHEADERSIZE 3   /* C standard doesn't allow `static const` variable to be init using another `static const` variable */
79e0c1b49fSNick Terrell static UNUSED_ATTR const size_t ZSTD_blockHeaderSize = ZSTD_BLOCKHEADERSIZE;
80e0c1b49fSNick Terrell typedef enum { bt_raw, bt_rle, bt_compressed, bt_reserved } blockType_e;
81e0c1b49fSNick Terrell 
82e0c1b49fSNick Terrell #define ZSTD_FRAMECHECKSUMSIZE 4
83e0c1b49fSNick Terrell 
84e0c1b49fSNick Terrell #define MIN_SEQUENCES_SIZE 1 /* nbSeq==0 */
85*65d1f550SNick Terrell #define MIN_CBLOCK_SIZE (1 /*litCSize*/ + 1 /* RLE or RAW */)   /* for a non-null block */
86*65d1f550SNick Terrell #define MIN_LITERALS_FOR_4_STREAMS 6
87e0c1b49fSNick Terrell 
88*65d1f550SNick Terrell typedef enum { set_basic, set_rle, set_compressed, set_repeat } SymbolEncodingType_e;
89e0c1b49fSNick Terrell 
90e0c1b49fSNick Terrell #define LONGNBSEQ 0x7F00
91e0c1b49fSNick Terrell 
92e0c1b49fSNick Terrell #define MINMATCH 3
93e0c1b49fSNick Terrell 
94e0c1b49fSNick Terrell #define Litbits  8
95*65d1f550SNick Terrell #define LitHufLog 11
96e0c1b49fSNick Terrell #define MaxLit ((1<<Litbits) - 1)
97e0c1b49fSNick Terrell #define MaxML   52
98e0c1b49fSNick Terrell #define MaxLL   35
99e0c1b49fSNick Terrell #define DefaultMaxOff 28
100e0c1b49fSNick Terrell #define MaxOff  31
101e0c1b49fSNick Terrell #define MaxSeq MAX(MaxLL, MaxML)   /* Assumption : MaxOff < MaxLL,MaxML */
102e0c1b49fSNick Terrell #define MLFSELog    9
103e0c1b49fSNick Terrell #define LLFSELog    9
104e0c1b49fSNick Terrell #define OffFSELog   8
105e0c1b49fSNick Terrell #define MaxFSELog  MAX(MAX(MLFSELog, LLFSELog), OffFSELog)
106*65d1f550SNick Terrell #define MaxMLBits 16
107*65d1f550SNick Terrell #define MaxLLBits 16
108e0c1b49fSNick Terrell 
109e0c1b49fSNick Terrell #define ZSTD_MAX_HUF_HEADER_SIZE 128 /* header + <= 127 byte tree description */
110e0c1b49fSNick Terrell /* Each table cannot take more than #symbols * FSELog bits */
111e0c1b49fSNick Terrell #define ZSTD_MAX_FSE_HEADERS_SIZE (((MaxML + 1) * MLFSELog + (MaxLL + 1) * LLFSELog + (MaxOff + 1) * OffFSELog + 7) / 8)
112e0c1b49fSNick Terrell 
1132aa14b1aSNick Terrell static UNUSED_ATTR const U8 LL_bits[MaxLL+1] = {
114e0c1b49fSNick Terrell      0, 0, 0, 0, 0, 0, 0, 0,
115e0c1b49fSNick Terrell      0, 0, 0, 0, 0, 0, 0, 0,
116e0c1b49fSNick Terrell      1, 1, 1, 1, 2, 2, 3, 3,
117e0c1b49fSNick Terrell      4, 6, 7, 8, 9,10,11,12,
118e0c1b49fSNick Terrell     13,14,15,16
119e0c1b49fSNick Terrell };
120e0c1b49fSNick Terrell static UNUSED_ATTR const S16 LL_defaultNorm[MaxLL+1] = {
121e0c1b49fSNick Terrell      4, 3, 2, 2, 2, 2, 2, 2,
122e0c1b49fSNick Terrell      2, 2, 2, 2, 2, 1, 1, 1,
123e0c1b49fSNick Terrell      2, 2, 2, 2, 2, 2, 2, 2,
124e0c1b49fSNick Terrell      2, 3, 2, 1, 1, 1, 1, 1,
125e0c1b49fSNick Terrell     -1,-1,-1,-1
126e0c1b49fSNick Terrell };
127e0c1b49fSNick Terrell #define LL_DEFAULTNORMLOG 6  /* for static allocation */
128e0c1b49fSNick Terrell static UNUSED_ATTR const U32 LL_defaultNormLog = LL_DEFAULTNORMLOG;
129e0c1b49fSNick Terrell 
1302aa14b1aSNick Terrell static UNUSED_ATTR const U8 ML_bits[MaxML+1] = {
131e0c1b49fSNick Terrell      0, 0, 0, 0, 0, 0, 0, 0,
132e0c1b49fSNick Terrell      0, 0, 0, 0, 0, 0, 0, 0,
133e0c1b49fSNick Terrell      0, 0, 0, 0, 0, 0, 0, 0,
134e0c1b49fSNick Terrell      0, 0, 0, 0, 0, 0, 0, 0,
135e0c1b49fSNick Terrell      1, 1, 1, 1, 2, 2, 3, 3,
136e0c1b49fSNick Terrell      4, 4, 5, 7, 8, 9,10,11,
137e0c1b49fSNick Terrell     12,13,14,15,16
138e0c1b49fSNick Terrell };
139e0c1b49fSNick Terrell static UNUSED_ATTR const S16 ML_defaultNorm[MaxML+1] = {
140e0c1b49fSNick Terrell      1, 4, 3, 2, 2, 2, 2, 2,
141e0c1b49fSNick Terrell      2, 1, 1, 1, 1, 1, 1, 1,
142e0c1b49fSNick Terrell      1, 1, 1, 1, 1, 1, 1, 1,
143e0c1b49fSNick Terrell      1, 1, 1, 1, 1, 1, 1, 1,
144e0c1b49fSNick Terrell      1, 1, 1, 1, 1, 1, 1, 1,
145e0c1b49fSNick Terrell      1, 1, 1, 1, 1, 1,-1,-1,
146e0c1b49fSNick Terrell     -1,-1,-1,-1,-1
147e0c1b49fSNick Terrell };
148e0c1b49fSNick Terrell #define ML_DEFAULTNORMLOG 6  /* for static allocation */
149e0c1b49fSNick Terrell static UNUSED_ATTR const U32 ML_defaultNormLog = ML_DEFAULTNORMLOG;
150e0c1b49fSNick Terrell 
151e0c1b49fSNick Terrell static UNUSED_ATTR const S16 OF_defaultNorm[DefaultMaxOff+1] = {
152e0c1b49fSNick Terrell      1, 1, 1, 1, 1, 1, 2, 2,
153e0c1b49fSNick Terrell      2, 1, 1, 1, 1, 1, 1, 1,
154e0c1b49fSNick Terrell      1, 1, 1, 1, 1, 1, 1, 1,
155e0c1b49fSNick Terrell     -1,-1,-1,-1,-1
156e0c1b49fSNick Terrell };
157e0c1b49fSNick Terrell #define OF_DEFAULTNORMLOG 5  /* for static allocation */
158e0c1b49fSNick Terrell static UNUSED_ATTR const U32 OF_defaultNormLog = OF_DEFAULTNORMLOG;
159e0c1b49fSNick Terrell 
160e0c1b49fSNick Terrell 
161e0c1b49fSNick Terrell /*-*******************************************
162e0c1b49fSNick Terrell *  Shared functions to include for inlining
163e0c1b49fSNick Terrell *********************************************/
ZSTD_copy8(void * dst,const void * src)164e0c1b49fSNick Terrell static void ZSTD_copy8(void* dst, const void* src) {
1652aa14b1aSNick Terrell #if defined(ZSTD_ARCH_ARM_NEON)
1662aa14b1aSNick Terrell     vst1_u8((uint8_t*)dst, vld1_u8((const uint8_t*)src));
1672aa14b1aSNick Terrell #else
168e0c1b49fSNick Terrell     ZSTD_memcpy(dst, src, 8);
1692aa14b1aSNick Terrell #endif
170e0c1b49fSNick Terrell }
171*65d1f550SNick Terrell #define COPY8(d,s) do { ZSTD_copy8(d,s); d+=8; s+=8; } while (0)
1722aa14b1aSNick Terrell 
1732aa14b1aSNick Terrell /* Need to use memmove here since the literal buffer can now be located within
1742aa14b1aSNick Terrell    the dst buffer. In circumstances where the op "catches up" to where the
1752aa14b1aSNick Terrell    literal buffer is, there can be partial overlaps in this call on the final
1762aa14b1aSNick Terrell    copy if the literal is being shifted by less than 16 bytes. */
ZSTD_copy16(void * dst,const void * src)177e0c1b49fSNick Terrell static void ZSTD_copy16(void* dst, const void* src) {
1782aa14b1aSNick Terrell #if defined(ZSTD_ARCH_ARM_NEON)
1792aa14b1aSNick Terrell     vst1q_u8((uint8_t*)dst, vld1q_u8((const uint8_t*)src));
1802aa14b1aSNick Terrell #elif defined(ZSTD_ARCH_X86_SSE2)
1812aa14b1aSNick Terrell     _mm_storeu_si128((__m128i*)dst, _mm_loadu_si128((const __m128i*)src));
1822aa14b1aSNick Terrell #elif defined(__clang__)
1832aa14b1aSNick Terrell     ZSTD_memmove(dst, src, 16);
1842aa14b1aSNick Terrell #else
1852aa14b1aSNick Terrell     /* ZSTD_memmove is not inlined properly by gcc */
1862aa14b1aSNick Terrell     BYTE copy16_buf[16];
1872aa14b1aSNick Terrell     ZSTD_memcpy(copy16_buf, src, 16);
1882aa14b1aSNick Terrell     ZSTD_memcpy(dst, copy16_buf, 16);
1892aa14b1aSNick Terrell #endif
190e0c1b49fSNick Terrell }
191*65d1f550SNick Terrell #define COPY16(d,s) do { ZSTD_copy16(d,s); d+=16; s+=16; } while (0)
192e0c1b49fSNick Terrell 
193e0c1b49fSNick Terrell #define WILDCOPY_OVERLENGTH 32
194e0c1b49fSNick Terrell #define WILDCOPY_VECLEN 16
195e0c1b49fSNick Terrell 
196e0c1b49fSNick Terrell typedef enum {
197e0c1b49fSNick Terrell     ZSTD_no_overlap,
198e0c1b49fSNick Terrell     ZSTD_overlap_src_before_dst
199e0c1b49fSNick Terrell     /*  ZSTD_overlap_dst_before_src, */
200e0c1b49fSNick Terrell } ZSTD_overlap_e;
201e0c1b49fSNick Terrell 
202e0c1b49fSNick Terrell /*! ZSTD_wildcopy() :
203e0c1b49fSNick Terrell  *  Custom version of ZSTD_memcpy(), can over read/write up to WILDCOPY_OVERLENGTH bytes (if length==0)
204e0c1b49fSNick Terrell  *  @param ovtype controls the overlap detection
205e0c1b49fSNick Terrell  *         - ZSTD_no_overlap: The source and destination are guaranteed to be at least WILDCOPY_VECLEN bytes apart.
206e0c1b49fSNick Terrell  *         - ZSTD_overlap_src_before_dst: The src and dst may overlap, but they MUST be at least 8 bytes apart.
207e0c1b49fSNick Terrell  *           The src buffer must be before the dst buffer.
208e0c1b49fSNick Terrell  */
209e0c1b49fSNick Terrell MEM_STATIC FORCE_INLINE_ATTR
ZSTD_wildcopy(void * dst,const void * src,ptrdiff_t length,ZSTD_overlap_e const ovtype)210e0c1b49fSNick Terrell void ZSTD_wildcopy(void* dst, const void* src, ptrdiff_t length, ZSTD_overlap_e const ovtype)
211e0c1b49fSNick Terrell {
212e0c1b49fSNick Terrell     ptrdiff_t diff = (BYTE*)dst - (const BYTE*)src;
213e0c1b49fSNick Terrell     const BYTE* ip = (const BYTE*)src;
214e0c1b49fSNick Terrell     BYTE* op = (BYTE*)dst;
215e0c1b49fSNick Terrell     BYTE* const oend = op + length;
216e0c1b49fSNick Terrell 
217e0c1b49fSNick Terrell     if (ovtype == ZSTD_overlap_src_before_dst && diff < WILDCOPY_VECLEN) {
218e0c1b49fSNick Terrell         /* Handle short offset copies. */
219e0c1b49fSNick Terrell         do {
220*65d1f550SNick Terrell             COPY8(op, ip);
221e0c1b49fSNick Terrell         } while (op < oend);
222e0c1b49fSNick Terrell     } else {
223e0c1b49fSNick Terrell         assert(diff >= WILDCOPY_VECLEN || diff <= -WILDCOPY_VECLEN);
224e0c1b49fSNick Terrell         /* Separate out the first COPY16() call because the copy length is
225e0c1b49fSNick Terrell          * almost certain to be short, so the branches have different
226e0c1b49fSNick Terrell          * probabilities. Since it is almost certain to be short, only do
227e0c1b49fSNick Terrell          * one COPY16() in the first call. Then, do two calls per loop since
228e0c1b49fSNick Terrell          * at that point it is more likely to have a high trip count.
229e0c1b49fSNick Terrell          */
230e0c1b49fSNick Terrell         ZSTD_copy16(op, ip);
231e0c1b49fSNick Terrell         if (16 >= length) return;
232e0c1b49fSNick Terrell         op += 16;
233e0c1b49fSNick Terrell         ip += 16;
234e0c1b49fSNick Terrell         do {
235e0c1b49fSNick Terrell             COPY16(op, ip);
236e0c1b49fSNick Terrell             COPY16(op, ip);
237e0c1b49fSNick Terrell         }
238e0c1b49fSNick Terrell         while (op < oend);
239e0c1b49fSNick Terrell     }
240e0c1b49fSNick Terrell }
241e0c1b49fSNick Terrell 
ZSTD_limitCopy(void * dst,size_t dstCapacity,const void * src,size_t srcSize)242e0c1b49fSNick Terrell MEM_STATIC size_t ZSTD_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
243e0c1b49fSNick Terrell {
244e0c1b49fSNick Terrell     size_t const length = MIN(dstCapacity, srcSize);
245e0c1b49fSNick Terrell     if (length > 0) {
246e0c1b49fSNick Terrell         ZSTD_memcpy(dst, src, length);
247e0c1b49fSNick Terrell     }
248e0c1b49fSNick Terrell     return length;
249e0c1b49fSNick Terrell }
250e0c1b49fSNick Terrell 
251e0c1b49fSNick Terrell /* define "workspace is too large" as this number of times larger than needed */
252e0c1b49fSNick Terrell #define ZSTD_WORKSPACETOOLARGE_FACTOR 3
253e0c1b49fSNick Terrell 
254e0c1b49fSNick Terrell /* when workspace is continuously too large
255e0c1b49fSNick Terrell  * during at least this number of times,
256e0c1b49fSNick Terrell  * context's memory usage is considered wasteful,
257e0c1b49fSNick Terrell  * because it's sized to handle a worst case scenario which rarely happens.
258e0c1b49fSNick Terrell  * In which case, resize it down to free some memory */
259e0c1b49fSNick Terrell #define ZSTD_WORKSPACETOOLARGE_MAXDURATION 128
260e0c1b49fSNick Terrell 
261e0c1b49fSNick Terrell /* Controls whether the input/output buffer is buffered or stable. */
262e0c1b49fSNick Terrell typedef enum {
263e0c1b49fSNick Terrell     ZSTD_bm_buffered = 0,  /* Buffer the input/output */
264e0c1b49fSNick Terrell     ZSTD_bm_stable = 1     /* ZSTD_inBuffer/ZSTD_outBuffer is stable */
265e0c1b49fSNick Terrell } ZSTD_bufferMode_e;
266e0c1b49fSNick Terrell 
267e0c1b49fSNick Terrell 
268e0c1b49fSNick Terrell /*-*******************************************
269e0c1b49fSNick Terrell *  Private declarations
270e0c1b49fSNick Terrell *********************************************/
271e0c1b49fSNick Terrell 
272e0c1b49fSNick Terrell /*
273e0c1b49fSNick Terrell  * Contains the compressed frame size and an upper-bound for the decompressed frame size.
274e0c1b49fSNick Terrell  * Note: before using `compressedSize`, check for errors using ZSTD_isError().
275e0c1b49fSNick Terrell  *       similarly, before using `decompressedBound`, check for errors using:
276e0c1b49fSNick Terrell  *          `decompressedBound != ZSTD_CONTENTSIZE_ERROR`
277e0c1b49fSNick Terrell  */
278e0c1b49fSNick Terrell typedef struct {
279*65d1f550SNick Terrell     size_t nbBlocks;
280e0c1b49fSNick Terrell     size_t compressedSize;
281e0c1b49fSNick Terrell     unsigned long long decompressedBound;
282e0c1b49fSNick Terrell } ZSTD_frameSizeInfo;   /* decompress & legacy */
283e0c1b49fSNick Terrell 
284e0c1b49fSNick Terrell /* ZSTD_invalidateRepCodes() :
285e0c1b49fSNick Terrell  * ensures next compression will not use repcodes from previous block.
286e0c1b49fSNick Terrell  * Note : only works with regular variant;
287e0c1b49fSNick Terrell  *        do not use with extDict variant ! */
288e0c1b49fSNick Terrell void ZSTD_invalidateRepCodes(ZSTD_CCtx* cctx);   /* zstdmt, adaptive_compression (shouldn't get this definition from here) */
289e0c1b49fSNick Terrell 
290e0c1b49fSNick Terrell 
291e0c1b49fSNick Terrell typedef struct {
292e0c1b49fSNick Terrell     blockType_e blockType;
293e0c1b49fSNick Terrell     U32 lastBlock;
294e0c1b49fSNick Terrell     U32 origSize;
295e0c1b49fSNick Terrell } blockProperties_t;   /* declared here for decompress and fullbench */
296e0c1b49fSNick Terrell 
297e0c1b49fSNick Terrell /*! ZSTD_getcBlockSize() :
298e0c1b49fSNick Terrell  *  Provides the size of compressed block from block header `src` */
299*65d1f550SNick Terrell /*  Used by: decompress, fullbench */
300e0c1b49fSNick Terrell size_t ZSTD_getcBlockSize(const void* src, size_t srcSize,
301e0c1b49fSNick Terrell                           blockProperties_t* bpPtr);
302e0c1b49fSNick Terrell 
303e0c1b49fSNick Terrell /*! ZSTD_decodeSeqHeaders() :
304e0c1b49fSNick Terrell  *  decode sequence header from src */
305*65d1f550SNick Terrell /*  Used by: zstd_decompress_block, fullbench */
306e0c1b49fSNick Terrell size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx* dctx, int* nbSeqPtr,
307e0c1b49fSNick Terrell                        const void* src, size_t srcSize);
308e0c1b49fSNick Terrell 
3092aa14b1aSNick Terrell /*
3102aa14b1aSNick Terrell  * @returns true iff the CPU supports dynamic BMI2 dispatch.
3112aa14b1aSNick Terrell  */
ZSTD_cpuSupportsBmi2(void)3122aa14b1aSNick Terrell MEM_STATIC int ZSTD_cpuSupportsBmi2(void)
3132aa14b1aSNick Terrell {
3142aa14b1aSNick Terrell     ZSTD_cpuid_t cpuid = ZSTD_cpuid();
3152aa14b1aSNick Terrell     return ZSTD_cpuid_bmi1(cpuid) && ZSTD_cpuid_bmi2(cpuid);
3162aa14b1aSNick Terrell }
317e0c1b49fSNick Terrell 
318e0c1b49fSNick Terrell #endif   /* ZSTD_CCOMMON_H_MODULE */
319