Skip to content

perf: enable x86-64-v2 kernels on a native v2 baseline - #1243

Open
anonrig wants to merge 6 commits into
mainfrom
cursor/x86-64-v2-optimizations-f0f8
Open

perf: enable x86-64-v2 kernels on a native v2 baseline#1243
anonrig wants to merge 6 commits into
mainfrom
cursor/x86-64-v2-optimizations-f0f8

Conversation

@anonrig

@anonrig anonrig commented Aug 31, 2026

Copy link
Copy Markdown
Member

Summary

Addresses #640: Windows 11 24H2, Rocky Linux 9, and RHEL 9 default to x86-64-v2 (SSSE3, SSE4.1, SSE4.2, POPCNT). Earlier revisions forced those kernels into default gcc/clang x86-64 builds with target("ssse3"). That changed the unity ada.cpp inlining budget on CodSpeed (which compiles the default x86-64 baseline, not v2): SetHash went from −12% to −15% with in-TU wrappers, and was still −7% after moving the kernels to a separate TU.

This revision does not pretend the default gcc TU is SSSE3. Rocky/RHEL 9 already define __SSSE3__ and compile the existing has_tabs_or_newline / host-delimiter SSSE3 paths. On that native v2 baseline (and on MSVC /arch:SSE4.2 or AVX):

  • Authority-delimiter scans (@ / \ ?) use an SSSE3 pshufb nibble table, matching the host-delimiter kernels already on main.
  • has_tabs_or_newline uses SSE4.1 ptest on the common miss path.
  • ADA_X86_64_V2 applies -march=x86-64-v2 (MSVC /arch:SSE4.2) when a distributor wants that baseline explicitly.

Default gcc/clang x86-64 codegen for setters matches main (SSE2 has_tabs, scalar authority tables). Parser / percent-encode keep target("ssse3") as on main. Public API and ABI are unchanged.

Test plan

  • Public-API tests for long-host parse, long userinfo, IPv6 [::1]:8080, tabs/newlines in a 16-byte window (including overlapping tail), and set_hash
  • Default gcc (ADA_X86_64_V2 off): preprocessor has ADA_SSE2 only; 351/351 tests passed (demo/cdemo/fuzzer/singleheader skipped locally)
  • -DADA_X86_64_V2=ON: preprocessor has ADA_SSSE3/ADA_SSE41/ADA_SSE42/ADA_POPCNT; 351/351 tests passed
  • CI green: all 55 checks on de728283, including lint-and-format, ARM/macOS/MSVC/clang-cl, ABI, sanitizers, fuzzing
  • CodSpeed: not alter performance vs main (47 untouched; SetHash / SetProtocol no longer regress)

Closes #640

Open in Web Open in Cursor 

cursoragent and others added 2 commits August 31, 2026 01:16
Windows 11 24H2, Rocky Linux 9, and RHEL 9 default to x86-64-v2
(SSSE3, SSE4.1, SSE4.2, POPCNT). Compile the existing SSSE3 host
and tab/newline scanners with per-function target attributes so
baseline x86-64 gcc/clang builds use them, add SSSE3/SSE2
authority-delimiter scans, and expose ADA_X86_64_V2 for a
whole-library -march=x86-64-v2 (MSVC /arch:SSE4.2).

Fixes #640

Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
GCC refused to always_inline SSSE3 kernels into SSE2 callers, and
-march=x86-64-v2 hid those helpers behind always_inline so tests
could not link. Keep target attributes on the default x86-64 path
and give the helpers a standalone symbol in both configurations.

Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
@codspeed-hq

codspeed-hq Bot commented Aug 31, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 47 untouched benchmarks
⏩ 4 skipped benchmarks1


Comparing cursor/x86-64-v2-optimizations-f0f8 (de72828) with main (e675447)

Open in CodSpeed

Footnotes

  1. 4 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@codecov

codecov Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 63.27%. Comparing base (e675447) to head (de72828).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1243   +/-   ##
=======================================
  Coverage   63.27%   63.27%           
=======================================
  Files          39       39           
  Lines        7705     7705           
  Branches     3514     3514           
=======================================
  Hits         4875     4875           
  Misses        752      752           
  Partials     2078     2078           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

NEON/SSE2/scalar definitions of has_tabs_or_newline and the
authority delimiter scanners were still always_inline, so
basic_tests could not link on those targets. Use ADA_X86_64_V2_SIMD
on every definition so a standalone symbol is always produced.

Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
@anonrig
anonrig marked this pull request as ready for review August 31, 2026 01:27
cursoragent and others added 3 commits August 31, 2026 01:40
CodSpeed flagged SetHash at -12% because the v2 helpers lost
always_inline (needed so ARM/macOS tests could link). Short setter
inputs never use the SSSE3 window; they paid a call and an inlining-
budget hit in the unity TU.

Restore ada_really_inline wrappers that stay on the scalar path for
<16 bytes and only call a targeted wide kernel for longer strings.
Cover the SIMD windows through parse/set_hash instead of private
helpers so other TUs do not need exported symbols.

Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
always_inline wrappers that called targeted SSSE3 kernels in the same
ada.cpp translation unit made CodSpeed worse: SetHash went from -12%
to -15% and eight other setters regressed. gcc will not inline across
that ISA boundary, and the extra target() functions steal the setter
inlining budget.

Put the wide kernels in simd_x86_64_v2.cpp (same split as
percent_encode). Short inputs stay on ada_really_inline scalar
wrappers with no target attribute. Also wrap the new parse test so
clang-format 22 is happy.

Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
Forcing SSSE3 via target() into the default SSE2 unity TU changed
setter inlining on CodSpeed's x86-64 baseline. SetHash and
SetProtocol still regressed after the kernels moved to their own TU,
because ADA_SSSE3 was defined globally and the inlined SSE2/scalar
helpers became external calls.

Do not pretend the default gcc TU is SSSE3. Rocky/RHEL 9 already
define __SSSE3__ and compile the existing kernels. On that native
v2 baseline, add SSSE3 authority-delimiter scans and SSE4.1 ptest
for has_tabs_or_newline. MSVC AVX/SSE4.2 implies the same ISA.
ADA_X86_64_V2 applies -march=x86-64-v2 when a distributor wants it.

Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
@cursor cursor Bot changed the title perf: enable x86-64-v2 kernels on default gcc/clang builds perf: enable x86-64-v2 kernels on a native v2 baseline Aug 31, 2026
@anonrig
anonrig requested a review from lemire September 1, 2026 01:11
@lemire

lemire commented Sep 1, 2026

Copy link
Copy Markdown
Member

@anonrig I think that this should be tested. The x64 processors on GH are surely v2 (it is hard or impossible to find processors than are not v2), so testing this flag in CI should work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide x86-64-v2 optimizations

3 participants