Skip to content

probe: the mask-algebra tail is worth replacing; the avx512vl gate is not needed; which replacement wins is NOT yet resolved #42

probe: the mask-algebra tail is worth replacing; the avx512vl gate is not needed; which replacement wins is NOT yet resolved

probe: the mask-algebra tail is worth replacing; the avx512vl gate is not needed; which replacement wins is NOT yet resolved #42

Workflow file for this run

on:
pull_request:
paths:
- 'src/simd*.rs'
- 'src/simd_nightly/**'
- 'src/simd_masking_ops.rs'
- 'src/hpc/amx_ops.rs'
- 'src/hpc/amx_matmul.rs'
- 'crates/simd-masking-parity/**'
- 'crates/neon-simd-parity/**'
- 'examples/ternlog_codegen_probe.rs'
- 'examples/amx_realization_report.rs'
- 'scripts/masking-parity.sh'
- 'scripts/codegen-witness.sh'
- 'scripts/neon-asm-rung3.sh'
- 'tools/gen_ternlog_bodies.py'
- '.cargo/**'
- 'Cargo.toml'
- 'src/lib.rs'
- '.github/workflows/simd-matrix.yaml'
merge_group:
push:
branches:
- master
- main
name: SIMD realization matrix
# Least privilege: nothing here pushes, comments, or releases. Every job
# only reads the tree, so the token is read-only and is not persisted into
# the checkout's git config (a repository-controlled command that runs after
# checkout would otherwise inherit whatever the repo's default token can do).
permissions:
contents: read
# Two axes, one program.
#
# realization × platform
# avx512 / avx2 / neon / wasm / scalar / nightly × x86_64 / aarch64 / wasm32
#
# Four rows run the SAME facade-only parity program unconditionally
# (`crates/simd-masking-parity`, via `scripts/masking-parity.sh <arm>`) — it
# has no idea which backend `simd.rs` selected, so a row proves "this
# realization is bit-identical to its scalar / bit-serial references" and
# nothing else. The avx512 row runs it ONLY on a runner that has avx512f;
# otherwise it degrades to an assembly-only assertion, and on that path the
# AVX-512 realization's bits are NOT proven in CI (the local v4 gate is the
# record for them). Where a row's assembly can be inspected, the tiny opt-3
# codegen oracle (`examples/ternlog_codegen_probe.rs`, via
# `scripts/codegen-witness.sh <arm>`) runs beside it: the parity program
# proves bits at the parity crate's release opt-level 2, the oracle proves the
# backend selected the instruction it is REQUIRED to select at opt-level 3.
# Neither replaces the other.
#
# The scalar realization has no host of its own: it is what `simd.rs` selects
# on wasm32 WITHOUT `+simd128`, so the `scalar` row is a wasm32 build with the
# feature off, run under node. `nightly` is the `core::simd` realization
# behind the opt-in `nightly-simd` feature and needs a nightly rustc.
#
# No workflow-global RUSTFLAGS here, on purpose: a global RUSTFLAGS REPLACES
# every cargo-config `rustflags` entry, which is how the v4 row would silently
# become a v3 row (see `.github/workflows/ci.yaml` tier4 for the incident).
# The v4 row passes `--config .cargo/config-v4.toml` through CARGO_ARGS.
env:
CARGO_TERM_COLOR: always
jobs:
native:
# x86_64 at x86-64-v3 (the AVX2 realization), PINNED EXPLICITLY via
# `.cargo/config-v3.toml`.
#
# ⊘ This row used to rely on v3 being `.cargo/config.toml`'s DEFAULT. That
# default is now `target-cpu=native`, so the pin is load-bearing rather
# than decorative, and the reason is two-sided-measured (2026-09-16, on an
# AVX-512 host): `codegen-witness.sh avx2` BARE reports
# "FAIL: ... has no packed logic" — it is grading vpternlog-carrying v4
# assembly against an assertion that says no vpternlog may appear — while
# the same command with `CARGO_ARGS='--config .cargo/config-v3.toml'`
# PASSES. Unpinned, this row would grade whichever tier the runner SKU
# happens to be; some Azure runner generations carry AVX-512, so it would
# be nondeterministic across reruns, not merely wrong.
#
# Also the ONLY row that can exercise AMX: the tile ops are
# runtime-gated and always compiled into native builds, so the report
# prints which gates this runner clears (`tile_available`/`available`
# false on a non-AMX runner is the expected, honest answer) and the
# encoding tests pin the assembled bytes without executing a tile op.
runs-on: ubuntu-latest
name: realization/avx2 × x86_64
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: generated ternlog bodies are current
run: python3 tools/gen_ternlog_bodies.py --check
- name: masking parity (x86-64-v3, pinned)
run: CARGO_ARGS='--config .cargo/config-v3.toml' bash scripts/masking-parity.sh native
- name: codegen witness (avx2, pinned to v3)
run: CARGO_ARGS='--config .cargo/config-v3.toml' bash scripts/codegen-witness.sh avx2
- name: AMX realization report (runtime-gated; prints this runner's gates)
run: cargo run --example amx_realization_report
- name: AMX encoding + detection tests (no tile op executes)
run: cargo test --lib -- hpc::amx_ops simd_amx
host-native:
# INFORMATIONAL, non-gating (`continue-on-error`). Testing the waters:
# what does a GitHub runner actually GIVE us under the new
# `target-cpu=native` default?
#
# Every other row in this matrix names its tier and asserts against it.
# This one names NOTHING and just reports — because the open question the
# native default raises is empirical and we do not have the answer:
# GitHub's ubuntu-latest pool is not one SKU, and some generations carry
# AVX-512 while others do not. The parity program's own header line
# (`avx512f=true|false`) is the reading; `lscpu` beside it is the
# corroboration.
#
# ANSWER, measured 2026-09-16 on this row's first run — and it is stronger
# than the question asked. Within ONE workflow run (35148155422), two jobs
# both `runs-on: ubuntu-latest`, both under the `target-cpu=native`
# default, reported DIFFERENT tiers:
#
# realization/nightly x x86_64 avx512f=TRUE
# realization/host-native x x86_64 avx512f=FALSE
#
# So the pool is HETEROGENEOUS and the tier is decided per JOB, not per
# run and not per repo. (The nightly row's failure on the previous head
# was caused by landing on an AVX-512 runner, which compiled
# `#[cfg(all(test, target_feature = "avx512f"))]` modules that had never
# been compiled in CI before — a real polyfill gap, fixed in c1bd7015.)
#
# That is exactly why `native` pins nothing and the portable row pins v3:
# unpinned, an ISA assertion here would be a coin flip per job, and a
# green run would prove only that today's scheduling was lucky.
#
# It is `continue-on-error` ON PURPOSE and must stay that way: a row whose
# result is "whatever this runner is" cannot gate a merge without making
# the merge depend on pool scheduling. If a future session wants to ASSERT
# a tier here, that is a different row with an explicit pin — do not
# promote this one by deleting the flag.
#
# What it can still catch, and why it is worth a row at all: the parity
# program must be bit-identical to its scalar references on WHATEVER
# realization it lands on. A red here is a real parity failure on a tier
# no pinned row happens to cover.
runs-on: ubuntu-latest
name: realization/host-native × x86_64 (informational)
continue-on-error: true
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: what silicon is this runner
run: lscpu | sed -n '1,/^Flags/p' | head -30
- name: masking parity (host-native, unpinned — READ THE HEADER LINE)
run: bash scripts/masking-parity.sh native
native-v4:
# Same host, AVX-512 realization via the v4 cargo config. Building and
# inspecting the assembly needs no AVX-512 silicon; RUNNING the parity
# binary and the probe's self-check does, and GitHub's ubuntu runners do
# not promise it — so the run steps are gated on /proc/cpuinfo and report
# SKIPPED loudly rather than SIGILL. The build + witness inspection (which
# asserts vpternlog was selected) always runs.
runs-on: ubuntu-latest
name: realization/avx512 × x86_64
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: v4
- name: detect the full x86-64-v4 AVX-512 set on this runner
id: cpu
# A v4 build may emit any of F/BW/CD/DQ/VL (the masking ops use the
# BW/VL byte and word compares beside the F ternlog), so avx512f alone
# would let a partially-capable host reach the run steps and SIGILL.
# All five or none.
run: |
has=1
for f in avx512f avx512bw avx512cd avx512dq avx512vl; do
grep -q -w "$f" /proc/cpuinfo || { echo "missing: $f"; has=0; }
done
echo "has=$has" >> "$GITHUB_OUTPUT"
grep -m1 'model name' /proc/cpuinfo || true
- name: build the parity program at x86-64-v4
run: env -u RUSTFLAGS cargo --config .cargo/config-v4.toml build --release --manifest-path crates/simd-masking-parity/Cargo.toml --bin simd-masking-parity --target x86_64-unknown-linux-gnu
- name: masking parity (native, v4 config)
if: steps.cpu.outputs.has == '1'
run: CARGO_ARGS='--config .cargo/config-v4.toml' bash scripts/masking-parity.sh native
- name: codegen witness (avx512) — assembly inspection + native self-check
if: steps.cpu.outputs.has == '1'
run: CARGO_ARGS='--config .cargo/config-v4.toml' bash scripts/codegen-witness.sh avx512
- name: codegen witness (avx512) — assembly inspection only (runner lacks avx512f)
if: steps.cpu.outputs.has == '0'
# The SAME script, in its asm-only mode — one implementation of the
# stale-assembly guard (`rm -f` + `touch`) and of the symbol
# attribution, not a second hand-rolled copy that drifts.
run: |
echo "::warning::runner lacks avx512f — v4 parity run and probe self-check SKIPPED; asserting the emitted assembly only"
env -u RUSTFLAGS WITNESS_NO_RUN=1 CARGO_ARGS='--config .cargo/config-v4.toml' bash scripts/codegen-witness.sh avx512
neon:
# aarch64 realization: cross-build on the x86 runner, run under qemu-user.
# Three rungs: parity under qemu (bits), the codegen witness (opt-3 NEON
# logic on v*.16b, GPR logic bounded), and rung 3 of the pre-existing NEON
# asm gate (`neon-simd-parity`, the wider type surface).
runs-on: ubuntu-latest
name: realization/neon × aarch64
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-unknown-linux-gnu
- run: rustup target add aarch64-unknown-linux-gnu
- uses: Swatinem/rust-cache@v2
with:
key: aarch64
- name: install aarch64 cross toolchain + qemu-user
run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu qemu-user-static
- name: masking parity (neon, qemu)
run: bash scripts/masking-parity.sh neon-qemu
- name: codegen witness (neon)
run: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc bash scripts/codegen-witness.sh neon aarch64-unknown-linux-gnu
- name: NEON asm rung 3
run: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc bash scripts/neon-asm-rung3.sh
wasm:
# wasm32 with +simd128 = the `simd_wasm` realization; wasm32 WITHOUT it is
# what `simd.rs` selects as the scalar realization — the scalar backend's
# only executable row, run through the identical program.
runs-on: ubuntu-latest
name: realization/wasm + scalar × wasm32
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-unknown-unknown
- run: rustup target add wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
key: wasm
- uses: actions/setup-node@v4
with:
node-version: "22"
- name: masking parity (wasm, +simd128)
run: bash scripts/masking-parity.sh wasm
- name: masking parity (scalar realization = wasm32 without simd128)
run: bash scripts/masking-parity.sh wasm-scalar
nightly:
# The `core::simd` realization behind the opt-in `nightly-simd` feature.
# Same program, same reference, nightly rustc; plus the lib tests that
# exercise the arm directly (masking ops, facade tests, AMX encodings —
# the latter because nightly's newer LLVM is where a dropped mnemonic
# first surfaces, as TF32 did).
runs-on: ubuntu-latest
name: realization/nightly × x86_64
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
key: nightly
- name: masking parity (nightly-simd)
run: bash scripts/masking-parity.sh nightly
- name: lib tests on the nightly arm
run: cargo +nightly test --lib --features nightly-simd -- simd_masking_ops simd::tests hpc::amx_ops simd_amx