Files
stockfish/.github/workflows/stockfish.yml
T
anematodeandJoost VandeVondele 8e711c29fe Add wasm32 and wasm32-relaxed-simd targets, and light optimizations
Lichess maintains some patches on top of SF dev to get it working with Emscripten. This PR moves some of these patches into SF and adds WASM to CI. It also adds a few changes in places where the x86 intrinsics don't cleanly map onto WebAssembly SIMD instructions; otherwise, we use Emscripten's x86 compatibility layer and take SSE4.1 code paths.

Summary of the compatibility changes:

- Define `wasm32` and `wasm32-relaxed-simd` targets.
    - We don't support wasm without SIMD; it'd be a waste of time.
- Add option to disable TBs
    - This is required because `tbprobe.cpp` pulls in `mmap`. This option can be used on any target, of course, but it's only enabled by default for wasm.
- Add compilation job + test to CI

And the changes for performance:

- Disable atomics for shared history on wasm
    - Atomics are always `seq_cst` there, which can be quite slow (even on the x86, stores are locked `xchg [mem], reg`)
- Add SSE code path to `get_changed_pieces`, modeled after the AVX2 path
- `_mm_mulhi_epi16` has a complicated emulation sequence, so for the pairwise multiplication, use an approach similar to the NEON impl.
- __int128 is gets lowered to runtime functions on wasm, so use the fallback impl for `mul_hi64`
- V8 does a poor job with the NNZ finding, so use a slightly different sequence there
- Add relaxed simd support for `m128_dpbusd`.

Some local perf figures (single-threaded speedtest):

```
wasm
Nodes/second               : 902523
sse4.1
Nodes/second               : 1155380
avx512icl
Nodes/second               : 1676184
```

Further avenues to explore:
- Optimize for performance under V8's experimental AVX revectorizer (Currently it's about +10% in my testing, but could definittely be more)
- Branch hinting. For example, run bench while collecting branch frequency info, then inject it late in the WASM compilation pipeline. I tried this locally and it didn't help much, but maybe I'm missing something.
- PGO. Gives +1.5% NPS locally, but hard to integrate with WASM compilation wrokflows

closes https://github.com/official-stockfish/Stockfish/pull/6875

No functional change
2026-06-09 19:35:05 +02:00

190 lines
6.7 KiB
YAML

name: Stockfish
on:
push:
tags:
- "*"
branches:
- master
- tools
- github_ci
pull_request:
branches:
- master
- tools
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
Prerelease:
name: Prerelease
if: github.repository == 'official-stockfish/Stockfish' && (github.ref == 'refs/heads/master' || (startsWith(github.ref_name, 'sf_') && github.ref_type == 'tag'))
runs-on: ubuntu-latest
needs: [Matrix, ARMCompilation, UniversalCompilation]
permissions:
contents: write # For deleting/creating a prerelease
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 0
# returns null if no pre-release exists
- name: Get Commit SHA of Latest Pre-release
run: |
# Install required packages
sudo apt-get update
sudo apt-get install -y curl jq
echo "COMMIT_SHA_TAG=$(jq -r 'map(select(.prerelease)) | first | .tag_name' <<< $(curl -s https://api.github.com/repos/${{ github.repository_owner }}/Stockfish/releases))" >> $GITHUB_ENV
# delete old previous pre-release and tag
- run: gh release delete ${{ env.COMMIT_SHA_TAG }} --cleanup-tag
if: env.COMMIT_SHA_TAG != 'null'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Make sure that an old ci that still runs on master doesn't recreate a prerelease
- name: Check Pullable Commits
id: check_commits
run: |
git fetch
CHANGES=$(git rev-list HEAD..origin/master --count)
echo "CHANGES=$CHANGES" >> $GITHUB_ENV
- name: Get last commit SHA
id: last_commit
run: echo "COMMIT_SHA=$(git rev-parse HEAD | cut -c 1-8)" >> $GITHUB_ENV
- name: Get commit date
id: commit_date
run: echo "COMMIT_DATE=$(git show -s --date=format:'%Y%m%d' --format=%cd HEAD)" >> $GITHUB_ENV
- name: Official Release?
id: official_release
# Check for "Official release version of Stockfish" in the commit message
run: |
if git log -1 --pretty=%B | grep -q "Official release version of Stockfish"; then
echo "OFFICIAL_RELEASE=true" >> $GITHUB_ENV
else
echo "OFFICIAL_RELEASE=false" >> $GITHUB_ENV
fi
# Get recent commits for release body
- name: Get commits in this push
id: recent_commits
run: |
COMMITS=$(git log \
--format="- [\`%h\`](https://github.com/${{ github.repository }}/commit/%H) *%s*" \
${{ github.event.before }}..HEAD)
echo "COMMITS<<EOF" >> $GITHUB_OUTPUT
echo "$COMMITS" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
# Create a new pre-release, the other upload_binaries.yml will upload the binaries
# to this pre-release.
- name: Create Prerelease
if: github.ref_name == 'master' && env.CHANGES == '0' && env.OFFICIAL_RELEASE == 'false'
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
with:
name: Stockfish dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
tag_name: stockfish-dev-${{ env.COMMIT_DATE }}-${{ env.COMMIT_SHA }}
prerelease: true
body: |
Precompiled binaries of the latest Stockfish development version, built automatically on every commit.
> [!NOTE]
> For stable, thoroughly tested builds use the [official releases](https://github.com/official-stockfish/Stockfish/releases).
> Pre-releases may contain bugs.
*Some platforms ship a **universal binary** that automatically selects the best
instruction set for your CPU - no manual selection needed.*
---
## Commits
${{ steps.recent_commits.outputs.COMMITS }}
[View all commits →](https://github.com/${{ github.repository }}/commits/master)
Matrix:
name: Prepare matrices
runs-on: ubuntu-latest
outputs:
arm_matrix: ${{ steps.set-arm-matrix.outputs.arm_matrix }}
universal_matrix: ${{ steps.set-universal-matrix.outputs.universal_matrix }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- id: set-arm-matrix
run: |
ARM_MATRIX=$(jq -c '.' .github/ci/arm_matrix.json)
echo "ARM_MATRIX=$ARM_MATRIX" >> $GITHUB_OUTPUT
- id: set-universal-matrix
run: |
UNIVERSAL_MATRIX=$(jq -c '.' .github/ci/universal_matrix.json)
echo "UNIVERSAL_MATRIX=$UNIVERSAL_MATRIX" >> $GITHUB_OUTPUT
# Testing Jobs
IWYU:
name: IWYU
uses: ./.github/workflows/iwyu.yml
Sanitizers:
name: Sanitizers
if: ${{ always() }}
uses: ./.github/workflows/sanitizers.yml
Tests:
name: Tests
if: ${{ always() }}
uses: ./.github/workflows/tests.yml
Matetrack:
name: Matetrack
if: ${{ always() }}
uses: ./.github/workflows/matetrack.yml
Games:
name: Games
if: ${{ always() }}
uses: ./.github/workflows/games.yml
CompilerCheck:
name: Compiler check
if: ${{ always() }}
uses: ./.github/workflows/avx2_compilers.yml
WASMCompilation:
name: WASM compilation
if: ${{ always() }}
uses: ./.github/workflows/wasm_compilation.yml
# Release Jobs
ARMCompilation:
name: Android builds
needs: [Matrix, Sanitizers, Tests, Matetrack, Games, CompilerCheck]
uses: ./.github/workflows/arm_compilation.yml
with:
matrix: ${{ needs.Matrix.outputs.arm_matrix }}
UniversalCompilation:
name: "Universal builds"
needs: [Matrix, Sanitizers, Tests, Matetrack, Games, CompilerCheck]
uses: ./.github/workflows/universal_compilation.yml
ARM_Binaries:
if: github.repository == 'official-stockfish/Stockfish'
name: Android uploads
needs: [Prerelease, Matrix]
uses: ./.github/workflows/upload_binaries.yml
with:
matrix: ${{ needs.Matrix.outputs.arm_matrix }}
permissions:
contents: write # For deleting/creating a (pre)release
secrets:
token: ${{ secrets.GITHUB_TOKEN }}
Universal_Binaries:
if: github.repository == 'official-stockfish/Stockfish'
name: Universal binaries
needs: [Prerelease, Matrix]
uses: ./.github/workflows/upload_binaries.yml
with:
matrix: ${{ needs.Matrix.outputs.universal_matrix }}
permissions:
contents: write # For deleting/creating a (pre)release
secrets:
token: ${{ secrets.GITHUB_TOKEN }}