[PATCH] x86: Fix non-temporal memset unreachable on AMD Zen 3/4/5
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Thu May 14 20:24:20 GMT 2026
On 06/05/26 02:38, zombie12138 wrote:
> On AMD Zen 3/4/5 with ERMS, the non-temporal memset path is unreachable
> because rep_stosb_threshold is set to SIZE_MAX (vectorized loop is faster
> than ERMS on these CPUs), but the non-temporal code path is nested inside
> the rep_stosb branch.
>
> The existing rescue logic at the Avoid_STOSB check only covers the case
> where the CPU lacks ERMS hardware support. It does not cover AMD Zen 3+
> where ERMS is supported but deliberately unused for performance reasons.
>
> Extend the condition to also lower rep_stosb_threshold when:
> - The user has not explicitly set x86_rep_stosb_threshold (respect tunables)
> - rep_stosb_threshold is higher than memset_non_temporal_threshold (NT gated)
>
> This makes the non-temporal path reachable for large memset operations,
> providing ~2x speedup on pre-faulted buffers larger than L3 cache.
>
> Tested on AMD Ryzen 7 8745HS (Zen 4):
> - Pre-faulted 64MB memset: 2.02 ms -> 0.94 ms (2.15x faster)
> - First-touch 64MB memset: 19.3 ms -> 21.3 ms (11% regression, expected:
> kernel clear_page cache warming bypassed by NT stores)
>
> * sysdeps/x86/dl-cacheinfo.h (dl_init_cacheinfo): Extend
> rep_stosb_threshold lowering condition to cover AMD Zen 3/4/5
> where ERMS is supported but stosb is disabled via threshold.
>
> Signed-off-by: zombie12138 <zombie12139@gmail.com>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=34129
LGTM, thanks.
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
> ---
> sysdeps/x86/dl-cacheinfo.h | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
> index b6e17b0e32..78929d1f2d 100644
> --- a/sysdeps/x86/dl-cacheinfo.h
> +++ b/sysdeps/x86/dl-cacheinfo.h
> @@ -1293,7 +1293,9 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
> /* Do `rep_stosb_thresh = non_temporal_thresh` after setting/getting the
> final value of `x86_memset_non_temporal_threshold`. In some cases this can
> be a matter of correctness. */
> - if (CPU_FEATURES_ARCH_P (cpu_features, Avoid_STOSB))
> + if (CPU_FEATURES_ARCH_P (cpu_features, Avoid_STOSB)
> + || (!TUNABLE_IS_INITIALIZED (x86_rep_stosb_threshold)
> + && rep_stosb_threshold > memset_non_temporal_threshold))
> rep_stosb_threshold
> = TUNABLE_GET (x86_memset_non_temporal_threshold, long int, NULL);
> TUNABLE_SET_WITH_BOUNDS (x86_rep_stosb_threshold, rep_stosb_threshold, 1,
More information about the Libc-alpha
mailing list