[RFC,v1,0/1] x86: Use TZCNT-based EVEX string variants on Hygon

Message ID 20260528081950.1417009-1-xiejiamei@hygon.cn (mailing list archive)
Headers
Series x86: Use TZCNT-based EVEX string variants on Hygon |

Message

Jiamei Xie May 28, 2026, 8:19 a.m. UTC
  Hi,

This RFC proposes using TZCNT instead of BSF to find the first set bit
in selected EVEX string routines on Hygon processors.

For non-zero input operands, TZCNT produces the same result as BSF.  The
modified paths only use TZCNT when the input mask is already known to be
non-zero, so the change does not rely on TZCNT's zero-input semantics.

Benchmarking shows that TZCNT is faster than BSF in several hot EVEX
string implementations on Hygon processors.  This RFC adds a new
preferred feature bit, Prefer_TZCNT_for_stringop, sets it for Hygon
processors, and uses it to select TZCNT-based EVEX variants for:

  strlen
  strcpy
  strchr
  strcmp
  strncmp
  memcmp

The implementation keeps the existing EVEX assembly as the common
source.  The default code path continues to use BSF through
FIND_FIRST_SET and FIND_FIRST_SETQ macros, while small TZCNT wrapper
files override those macros and include the original implementation.

This keeps the change localized and avoids duplicating the full assembly
sources.  Dispatch for non-Hygon processors is unchanged.

Benchmark results relative to the existing EVEX variants:

Function          Hygon model 7   Hygon model 8
__strlen_evex        +12.32%         +11.89%
__strcpy_evex         +5.83%          +4.25%
__strchr_evex         +9.21%          +9.76%
__strcmp_evex         +6.28%          +7.79%
__memcmp_evex        +10.30%         +10.99%
__strncmp_evex        +4.26%          +4.92%

Positive numbers mean the TZCNT variant is faster than the existing
EVEX variant.

Feedback is welcome.

Thanks

Jiamei Xie (1):
  x86: Add TZCNT variants for selected Hygon string functions

 sysdeps/x86/cpu-features.c                    |  5 +++
 ...cpu-features-preferred_feature_index_1.def |  1 +
 sysdeps/x86_64/multiarch/Makefile             |  6 ++++
 sysdeps/x86_64/multiarch/ifunc-avx2.h         |  8 +++++
 sysdeps/x86_64/multiarch/ifunc-impl-list.c    | 36 +++++++++++++++++++
 sysdeps/x86_64/multiarch/ifunc-memcmp.h       | 13 ++++++-
 sysdeps/x86_64/multiarch/ifunc-strcpy.h       | 13 ++++++-
 .../multiarch/memcmp-evex-movbe-tzcnt.S       |  8 +++++
 sysdeps/x86_64/multiarch/memcmp-evex-movbe.S  | 23 ++++--------
 sysdeps/x86_64/multiarch/memcmp.c             |  1 +
 sysdeps/x86_64/multiarch/strchr-evex-tzcnt.S  |  8 +++++
 sysdeps/x86_64/multiarch/strchr-evex.S        | 16 ++++-----
 sysdeps/x86_64/multiarch/strchr.c             |  5 +++
 sysdeps/x86_64/multiarch/strcmp-evex-tzcnt.S  |  5 +++
 sysdeps/x86_64/multiarch/strcmp-evex.S        | 34 +++++++++---------
 sysdeps/x86_64/multiarch/strcmp.c             |  9 ++++-
 sysdeps/x86_64/multiarch/strcpy-evex-tzcnt.S  |  7 ++++
 sysdeps/x86_64/multiarch/strcpy-evex.S        | 18 +++++-----
 sysdeps/x86_64/multiarch/strcpy.c             |  1 +
 sysdeps/x86_64/multiarch/strlen-evex-base.S   | 14 ++++----
 sysdeps/x86_64/multiarch/strlen-evex-tzcnt.S  | 10 ++++++
 sysdeps/x86_64/multiarch/strlen.c             |  1 +
 sysdeps/x86_64/multiarch/strncmp-evex-tzcnt.S |  6 ++++
 sysdeps/x86_64/multiarch/strncmp.c            |  9 ++++-
 sysdeps/x86_64/sysdep.h                       |  8 +++++
 25 files changed, 205 insertions(+), 60 deletions(-)
 create mode 100644 sysdeps/x86_64/multiarch/memcmp-evex-movbe-tzcnt.S
 create mode 100644 sysdeps/x86_64/multiarch/strchr-evex-tzcnt.S
 create mode 100644 sysdeps/x86_64/multiarch/strcmp-evex-tzcnt.S
 create mode 100644 sysdeps/x86_64/multiarch/strcpy-evex-tzcnt.S
 create mode 100644 sysdeps/x86_64/multiarch/strlen-evex-tzcnt.S
 create mode 100644 sysdeps/x86_64/multiarch/strncmp-evex-tzcnt.S