Uh oh!
There was an error while loading. Please reload this page.
zstd: use x86 feature infrastructure for BMI2 dispatch - #4767
Open
uarif1 wants to merge 2 commits into
Open
Conversation
added 2 commits
September 7, 2026 07:30
When dynamic BMI2 dispatch is disabled, the BMI2-specific functions are not compiled and each selector is conditionally compiled to avoid naming them. The selector-level preprocessor guards will be replaced with a predicate that becomes constant false when dynamic BMI2 dispatch is disabled. Although the compiler eliminates an if (0) branch, it must still parse and resolve the BMI2 function referenced by it. Add aliases from the unavailable BMI2 function names to their default implementations. These aliases make the names valid without emitting BMI2-specific code. The selectors remain unchanged in this patch, so the aliases are not used yet and there is no code-generation change. Signed-off-by: Usama Arif <usama.arif@linux.dev>
Dynamic BMI2 dispatch probes CPUID when a compression or decompression context is initialized. It caches the result in the context and tests the caller-provided state at each final dispatch site. This is suitable for standalone userspace, but prevents integrations such as the Linux kernel from applying their own CPU feature policy at those sites. Add ZSTD_USE_BMI2() for final selectors and ZSTD_SET_BMI2() for context initialization. Their default definitions preserve existing userspace behavior, while allowing an integration to replace both the selection policy and cached state. For the Linux kernel import, normal x86 objects now select BMI2 through cpu_feature_enabled(X86_FEATURE_BMI2), allowing x86 alternatives to resolve the check. Preboot objects, identified by __DISABLE_EXPORTS, retain the existing CPUID-backed path because the normal kernel CPU feature infrastructure is unavailable there. Use the fallback aliases added by the preceding change when target- attributed variants are absent, and verify that the import process consumes ZSTD_LINUX_KERNEL. A 4 KiB zstd-generic crypto_acomp benchmark in a one-vCPU KVM guest gave these median results: Before After Change Compression 16,634 ns/op 13,394 ns/op -19.5% Decompression 3,480 ns/op 963 ns/op -72.3% Signed-off-by: Usama Arif <usama.arif@linux.dev>
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 freeto 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.
Zstd currently probes CPUID whenever a compression or decompression
context is initialized, stores the result in the context, and tests that
value at each BMI2 dispatch site. For normal x86 kernel builds this
duplicates the kernel's CPU feature infrastructure, bypasses its feature
policy, and leaves an ordinary runtime test in the dispatch path.
Use cpu_feature_enabled(X86_FEATURE_BMI2) directly at the dispatch sites
for normal x86 kernel objects. This uses the x86 alternatives-backed
static CPU feature mechanism, allowing the feature test to be resolved at
boot instead of loading and testing a value stored in each context.
ZSTD_USE_BMI2() keeps the other build modes working as before. It expands
to the caller-provided flag for standalone and preboot builds and to false
when DYNAMIC_BMI2 is disabled. ZSTD_SET_BMI2() similarly stores the
caller-provided state only when it will be used, avoiding preprocessor
conditionals at the context initialization sites.
Patch 1 adds aliases from BMI2 function names to their default
implementations when the BMI2 variants are not compiled. This is a
no-functional-change preparation: after patch 2 removes the affected
selector-level preprocessor guards, the compiler must still resolve the
function named in an if (0) branch before eliminating it.
Patch 2 adds ZSTD_USE_BMI2() and ZSTD_SET_BMI2(), converts the runtime
selectors, and avoids Zstd's private CPUID probes in normal x86 kernel
objects. The kernel-specific policy lives in zstd_deps.h. Preboot builds
are excluded because the normal alternatives infrastructure is not
available there, so they retain the existing raw-CPUID dispatch.
A 4 KiB zstd-generic crypto_acomp benchmark [1] in a one-vCPU KVM guest
gave these median results:
Compression 16,634 ns 13,394 ns -19.5%
Decompression 3,480 ns 963 ns -72.3%
The improvement is especially large in a guest because raw CPUID causes
a VM exit.
This was originally posted on the kernel mailing list [2].
[1] https://gist.github.com/uarif1/5cf02f0e22c23f0d1b3d84348f12914c
[2] https://lore.kernel.org/all/20260901110850.1805747-1-usama.arif@linux.dev/