Repository navigation
Add Intel APX-optimized decompression paths with runtime dispatch - #4888
Draft
gangdeng-intel wants to merge 5 commits into
Draft
gangdeng-intel wants to merge 5 commits into
gangdeng-intel wants to merge 5 commits into
Conversation
… target attribute Detect Intel APX support at compile time (STATIC_APXF) and runtime (DYNAMIC_APXF, ZSTD_cpuid_apx_f), and add APXF_TARGET_ATTRIBUTE for functions that should be compiled with APX instructions enabled. This is shared infrastructure used by the APX-optimized decompression paths added in subsequent commits.
Add XXH64_update_apxf, an APX-enabled variant of XXH64_update, with runtime dispatch based on CPU support (DYNAMIC_APXF). This speeds up the frame content checksum verification performed during decompression.
Add HUF_flags_apxf to HUF_flags_e, used by the decompressor to opt into the APX-optimized Huffman decoding fast loop added in the next commit.
Add HUF_decompress4X1_usingDTable_internal_fast_asm_loop_apx, an APX-enabled variant of the 4-stream Huffman fast decoding loop. It uses extended GPRs (EGPR) to avoid the stack-spill area needed for ip[1,2,3]/olimit in the baseline loop, PUSH2/POP2 to halve prologue and epilogue push/pop uops, NDD and NF-prefixed instructions to reduce flag-write pressure, and CCMP to collapse the three ip-ordering checks into a single chained compare. Existing BMI2 instructions are preserved. Dispatch to this loop is gated on HUF_flags_apxf, set by the decompressor when the CPU supports APX (see previous commits).
Add ZSTD_cpuSupportsApxf() and an apxf field on ZSTD_DCtx, detected once per context lifetime (DYNAMIC_APXF). Use it to: - select the APX-optimized Huffman fast loop via HUF_flags_apxf when decoding literals blocks - dispatch to APX-compiled variants of ZSTD_decompressSequences(), ZSTD_decompressSequencesSplitLitBuffer(), and ZSTD_decompressSequencesLong() - call XXH64_update_apxf() instead of XXH64_update() when validating the frame content checksum This completes the APX-optimized decompression path.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds optional decompression code paths that use Intel® Advanced Performance Extensions (Intel® APX). The CPU is checked at runtime, and the APX paths are selected only on processors and operating systems that support APX. All other platforms continue to use the existing code paths unchanged.
The changes are expected to improve decompression performance on future APX-capable processors.
Intel APX architecture specification:
https://www.intel.com/content/www/us/en/content-details/861610/intel-advanced-performance-extensions-intel-apx-architecture-specification.html
Background
Intel APX extends the x86-64 instruction set with, among other features:
Zstd's decompression hot paths, especially the Huffman fast loop and sequence decoding, are register-heavy and branchy, so they can benefit from these features.
Changes
The PR is organized as five self-contained commits:
common: add APX detection and target attributeSTATIC_APXF, set when the compiler targets APX, i.e.__APX_F__is defined, e.g. with-mapxf) and runtime dispatch control (DYNAMIC_APXF)DYNAMIC_APXFis enabled only on x86-64 with clang >= 20 or gcc >= 15, since APX is available only in 64-bit modeDYNAMIC_APXFis forced to 0 for Linux kernel builds (ZSTD_LINUX_KERNEL), so no APX code or extended-register usage is introduced into the kernelZSTD_cpuSupportsApx()function. The sharedZSTD_cpuid()is left unchanged. The result is computed once per process and cached, so creating aZSTD_CCtx/ZSTD_DCtxcosts no additional CPUID/XGETBV instructions (cf. the per-context CPUID cost discussed in zstd: use x86 feature infrastructure for BMI2 dispatch #4767)APXF_TARGET_ATTRIBUTEfor functions compiled with APX code generation enabledcommon: add APX-optimized XXH64_updateXXH64_update_apxf(), an APX-compiled variant used for frame checksum verification during decompressioncommon: add HUF_flags_apxf flagHUF_flags_eflag used by the decompressor to opt into the APX Huffman fast loopdecompress: add APX-optimized HUF_decompress4X1 fast asm loophuf_decompress_amd64.Sip[1..3]/olimit, PUSH2/POP2 in the prologue and epilogue, NDD/NF to reduce flag-write pressure, and CCMP to merge the threeipordering checks into one chained compareSTATIC_APXF(e.g.-mapxf), the APX loop is used directly without runtime detectiondecompress: add APX dynamic dispatch for sequence decodingZSTD_DCtxat initializationZSTD_decompressSequences(),ZSTD_decompressSequencesSplitLitBuffer(), andZSTD_decompressSequencesLong()XXH64_updatewhen APX is availableCompatibility
DYNAMIC_APXFevaluates to 0 and none of the APX code is compiled.-DDYNAMIC_APXF=0.-mapxf): the whole library is already compiled for APX, so no runtime detection or duplicated_apxfC functions are generated; only the APX Huffman asm loop is added.ZSTD_USE_BMI2()/ Linux kernel CPU-feature handling, is preserved. The APX check is evaluated first, and the code falls through to the existing logic when APX is unavailable.Code size
With APX-capable compilers, the APX variants are compiled in addition to the existing code paths. Measured with gcc 16.2.1 on x86-64 Linux using the default Makefile settings (
make -C programs zstd,make -C lib libzstd, i.e.-O3);textas reported bysize:programs/zstdlib/libzstd.soBuilding this PR with
-DDYNAMIC_APXF=0produces the same sizes as upstream/dev.Testing
make test(includingfuzzer,zstreamtest,decodecorpus,legacy,invalidDictionaries, and the CLI tests), with the APX code paths active. With clang 23 this requiredMOREFLAGS=-Wno-unused-but-set-global, because of a new-Wunused-but-set-globalwarning inprograms/zstdcli.c. The warning also occurs on upstream/dev and is unrelated to this PR.-Werror;make testpassed.-m32 -fPICbuilds of the CPU-detection code with gcc and clang (APX code is correctly excluded).make -C contrib/linux-kernel testpasses; APX is compiled out of the imported sources.-Werror.Performance
The changes are expected to improve decompression performance on future APX-capable processors.
No regression on non-APX hardware. Decompression speed was compared between upstream/dev and this PR on an Intel Core i9-12900K (Alder Lake, P-core pinned, turbo disabled). Both were built with the default Makefile flags. The test used
zstd -b -d -i30on the Silesia corpus pre-compressed at levels 1–19 (plus one level-3 file without checksum), with 3 interleaved rounds per build:Checklist
A gain in one configuration is not a general gain: see the Performance section of CONTRIBUTING.md.
Tools used
Copilot (AI) was used to help write the code changes, and run the benchmarks and tests. I reviewed the diff and the benchmark data before submitting.