Skip to content

Commit 3932a21

Browse files
authored
Merge pull request #350 from AdaWorldAPI/ccr-9f3b8075-74u47l
ci: run the nightly jobs on nightly; skip cpu_guard under Miri
2 parents 9402e57 + 5f60c10 commit 3932a21

47 files changed

Lines changed: 154 additions & 132 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/ci.yaml‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,11 @@ jobs:
342342
- uses: dtolnay/rust-toolchain@nightly
343343
- uses: Swatinem/rust-cache@v2
344344
- name: cargo check (nightly + nightly-simd feature)
345-
run: cargo check -p ndarray --features approx,serde,rayon,nightly-simd
345+
# `+nightly`: rust-toolchain.toml pins stable and takes precedence over
346+
# the toolchain dtolnay installs, so a plain `cargo` here is stable.
347+
run: cargo +nightly check -p ndarray --features approx,serde,rayon,nightly-simd
346348
- name: cargo check (nightly + nightly-simd + hpc-extras)
347-
run: cargo check -p ndarray --features approx,serde,rayon,nightly-simd,hpc-extras
349+
run: cargo +nightly check -p ndarray --features approx,serde,rayon,nightly-simd,hpc-extras
348350

349351
blas-msrv:
350352
runs-on: ubuntu-latest
@@ -418,11 +420,17 @@ jobs:
418420
steps:
419421
- uses: actions/checkout@v4
420422
- uses: dtolnay/rust-toolchain@nightly
423+
with:
424+
# careful rebuilds std from source; without rust-src it stalls
425+
# (seen locally: no compiler process, no output, for 25 min).
426+
components: rust-src
421427
- uses: Swatinem/rust-cache@v2
422428
- uses: taiki-e/install-action@nextest
423429
- name: Install cargo-careful
424430
run: cargo install cargo-careful
425-
- run: cargo careful nextest run -Zcareful-sanitizer --features="$FEATURES"
431+
# `+nightly`: see nightly-simd-polyfill. On stable, careful fails at
432+
# `rustc --print target-spec-json` ("output is invalid JSON").
433+
- run: cargo +nightly careful nextest run -Zcareful-sanitizer --features="$FEATURES"
426434

427435
docs:
428436
# Nightly needed for --cfg docsrs. Only on merge queue / push.
@@ -434,7 +442,11 @@ jobs:
434442
steps:
435443
- uses: actions/checkout@v4
436444
- uses: dtolnay/rust-toolchain@nightly
437-
- run: cargo doc --no-deps --all-features
445+
# `+nightly`: see nightly-simd-polyfill. Features match
446+
# `[package.metadata.docs.rs]`: `--all-features` cannot build, because
447+
# `intel-mkl`/`openblas` and `runtime-dispatch`/`nightly-simd` are
448+
# mutually exclusive (`compile_error!`).
449+
- run: cargo +nightly doc --no-deps --features approx,serde,rayon
438450

439451
conclusion:
440452
needs:

‎scripts/miri-tests.sh‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ cargo +nightly miri nextest run -v \
6464
test(/^hpc::/) - test(/^hpc::byte_scan/)
6565
) and !test(/^simd::tests::/)
6666
and !test(/^hpc::framebuffer::pyramid_tests::/)
67+
and !test(/^cpu_guard::/)
6768
'
6869
#
69-
# Filter rationale (3-clause AND):
70+
# Filter rationale (4-clause AND):
7071
#
7172
# 1. `!(test(/^hpc::/) - test(/^hpc::byte_scan/))`
7273
# Skip everything in `hpc::*` EXCEPT `hpc::byte_scan` (the scalar-fallback
@@ -85,3 +86,8 @@ cargo +nightly miri nextest run -v \
8586
# loops over SIMD-shaped data). Not a UB signal — pure runtime cost.
8687
# Re-enable once the test fixtures are sized down or the loops are
8788
# cfg(miri)-shortened.
89+
#
90+
# 4. `!test(/^cpu_guard::/)`
91+
# `cpu_guard` reads the CPU with `cpuid`, which is inline assembly; Miri
92+
# rejects it ("inline assembly is not supported"). The pre-`main` hook is
93+
# `cfg(not(miri))` for the same reason, so test binaries start under Miri.

‎src/backend/kernels_avx512.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::simd::{F32x16, F64x8};
2121
// BLAS Level 1 — 12 functions (compat types)
2222
// ═══════════════════════════════════════════════════════════════════
2323

24-
/// Dot product: sum(x[i] * y[i]) using 4x-unrolled FMA.
24+
/// Dot product: sum(x\[i\] * y\[i\]) using 4x-unrolled FMA.
2525
/// # Safety
2626
/// Caller must ensure AVX-512F is available (`simd_caps().avx512f`).
2727
#[cfg(target_arch = "x86_64")]
@@ -167,7 +167,7 @@ pub fn scal_f64(alpha: f64, x: &mut [f64]) {
167167
}
168168
}
169169

170-
/// L1 norm: sum(|x[i]|) (f32, 16-wide).
170+
/// L1 norm: sum(|x\[i\]|) (f32, 16-wide).
171171
/// # Safety
172172
/// Caller must ensure AVX-512F is available (`simd_caps().avx512f`).
173173
#[cfg(target_arch = "x86_64")]
@@ -185,7 +185,7 @@ pub fn asum_f32(x: &[f32]) -> f32 {
185185
sum
186186
}
187187

188-
/// L1 norm: sum(|x[i]|) (f64, 8-wide).
188+
/// L1 norm: sum(|x\[i\]|) (f64, 8-wide).
189189
/// # Safety
190190
/// Caller must ensure AVX-512F is available (`simd_caps().avx512f`).
191191
#[cfg(target_arch = "x86_64")]
@@ -203,7 +203,7 @@ pub fn asum_f64(x: &[f64]) -> f64 {
203203
sum
204204
}
205205

206-
/// L2 norm: sqrt(sum(x[i]^2)) (f32, 16-wide FMA).
206+
/// L2 norm: sqrt(sum(x\[i\]^2)) (f32, 16-wide FMA).
207207
/// # Safety
208208
/// Caller must ensure AVX-512F is available (`simd_caps().avx512f`).
209209
#[cfg(target_arch = "x86_64")]
@@ -225,7 +225,7 @@ pub fn nrm2_f32(x: &[f32]) -> f32 {
225225
sum.sqrt()
226226
}
227227

228-
/// L2 norm: sqrt(sum(x[i]^2)) (f64, 8-wide FMA).
228+
/// L2 norm: sqrt(sum(x\[i\]^2)) (f64, 8-wide FMA).
229229
/// # Safety
230230
/// Caller must ensure AVX-512F is available (`simd_caps().avx512f`).
231231
#[cfg(target_arch = "x86_64")]

‎src/backend/native.rs‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,10 @@ macro_rules! dispatch {
167167
// ─── BLAS-1 dispatch ──────────────────────────────────────────────
168168

169169
dispatch!(
170-
/// Dot product: result = sum(x[i] * y[i]) (f32).
170+
/// Dot product: result = sum(x\[i\] * y\[i\]) (f32).
171171
dot_f32(x: &[f32], y: &[f32]) -> f32);
172172
dispatch!(
173-
/// Dot product: result = sum(x[i] * y[i]) (f64).
173+
/// Dot product: result = sum(x\[i\] * y\[i\]) (f64).
174174
dot_f64(x: &[f64], y: &[f64]) -> f64);
175175
dispatch!(
176176
/// AXPY: y = alpha * x + y (f32).
@@ -186,16 +186,16 @@ dispatch!(
186186
/// Scale: x = alpha * x (f64).
187187
scal_f64(alpha: f64, x: &mut [f64]));
188188
dispatch!(
189-
/// L2 norm: sqrt(sum(x[i]^2)) (f32).
189+
/// L2 norm: sqrt(sum(x\[i\]^2)) (f32).
190190
nrm2_f32(x: &[f32]) -> f32);
191191
dispatch!(
192-
/// L2 norm: sqrt(sum(x[i]^2)) (f64).
192+
/// L2 norm: sqrt(sum(x\[i\]^2)) (f64).
193193
nrm2_f64(x: &[f64]) -> f64);
194194
dispatch!(
195-
/// L1 norm: sum(|x[i]|) (f32).
195+
/// L1 norm: sum(|x\[i\]|) (f32).
196196
asum_f32(x: &[f32]) -> f32);
197197
dispatch!(
198-
/// L1 norm: sum(|x[i]|) (f64).
198+
/// L1 norm: sum(|x\[i\]|) (f64).
199199
asum_f64(x: &[f64]) -> f64);
200200

201201
// ─── GEMM dispatch ───────────────────────────────────────────────
@@ -284,7 +284,7 @@ pub fn gemm_f64(
284284
/// GEMV: y = alpha * A * x + beta * y (f32, row-major).
285285
///
286286
/// SIMD tiers compute each row via [`dot_f32`]; the scalar tier uses
287-
/// the byte-stable [`scalar::gemv_f32`] reference.
287+
/// the byte-stable `scalar::gemv_f32` reference.
288288
pub fn gemv_f32(m: usize, n: usize, alpha: f32, a: &[f32], lda: usize, x: &[f32], beta: f32, y: &mut [f32]) {
289289
if m == 0 {
290290
return; // no rows ⇒ no-op; must not slice `x[..n]` (scalar ref returns too)
@@ -307,7 +307,7 @@ pub fn gemv_f32(m: usize, n: usize, alpha: f32, a: &[f32], lda: usize, x: &[f32]
307307
/// GEMV: y = alpha * A * x + beta * y (f64, row-major).
308308
///
309309
/// SIMD tiers compute each row via [`dot_f64`]; the scalar tier uses
310-
/// the byte-stable [`scalar::gemv_f64`] reference.
310+
/// the byte-stable `scalar::gemv_f64` reference.
311311
pub fn gemv_f64(m: usize, n: usize, alpha: f64, a: &[f64], lda: usize, x: &[f64], beta: f64, y: &mut [f64]) {
312312
if m == 0 {
313313
return; // no rows ⇒ no-op; must not slice `x[..n]` (scalar ref returns too)

‎src/bitwise.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ const HAMMING_WITHIN_BLOCK: usize = 256;
204204
///
205205
/// Exact, not approximate: the running total only grows, so once it exceeds
206206
/// `max` the final distance must too, and the remaining bytes are skipped.
207-
/// The check happens after every [`HAMMING_WITHIN_BLOCK`]-byte block, so a
207+
/// The check happens after every `HAMMING_WITHIN_BLOCK`-byte block, so a
208208
/// reject costs at most one block beyond the point where the budget ran out.
209209
/// Like [`hamming_distance_raw`], unequal lengths measure the common prefix.
210210
///

‎src/cpu_guard.rs‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ pub fn assert_build_cpu() {
348348

349349
/// The pre-`main` hook. Prints and exits instead of panicking: unwinding out
350350
/// of a loader-invoked `extern "C"` function would abort with no message.
351+
///
352+
/// Not installed under Miri: `cpuid` is inline assembly, which Miri cannot
353+
/// execute, and an interpreter has no CPU to check.
354+
#[cfg(not(miri))]
351355
extern "C" fn guard_before_main() {
352356
if let Err(mismatch) = check_build_cpu() {
353357
use std::io::Write;
@@ -358,17 +362,17 @@ extern "C" fn guard_before_main() {
358362

359363
// The loader calls every function pointer in these sections before `main`.
360364
// `#[used]` keeps the static even though nothing references it.
361-
#[cfg(any(target_os = "linux", target_os = "android", target_os = "freebsd"))]
365+
#[cfg(all(not(miri), any(target_os = "linux", target_os = "android", target_os = "freebsd")))]
362366
#[used]
363367
#[link_section = ".init_array"]
364368
static GUARD_BEFORE_MAIN: extern "C" fn() = guard_before_main;
365369

366-
#[cfg(any(target_os = "macos", target_os = "ios"))]
370+
#[cfg(all(not(miri), any(target_os = "macos", target_os = "ios")))]
367371
#[used]
368372
#[link_section = "__DATA,__mod_init_func"]
369373
static GUARD_BEFORE_MAIN: extern "C" fn() = guard_before_main;
370374

371-
#[cfg(target_os = "windows")]
375+
#[cfg(all(not(miri), target_os = "windows"))]
372376
#[used]
373377
#[link_section = ".CRT$XCU"]
374378
static GUARD_BEFORE_MAIN: extern "C" fn() = guard_before_main;

‎src/heel_f64x8.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::simd::{array_chunks, F64x8};
1515
///
1616
/// `distances[i]` = distance for HEEL plane i.
1717
/// `weights[i]` = importance weight for plane i.
18-
/// Returns: Σ(distances[i] × weights[i]).
18+
/// Returns: Σ(distances\[i\] × weights\[i\]).
1919
///
2020
/// One F64x8 multiply + reduce_sum. On AVX-512: single vmulpd + vreducepd.
2121
/// On AVX2: 2× vmulpd + 2× haddpd. Scalar: 8 multiplies + sum.
@@ -28,7 +28,7 @@ pub fn heel_weighted_distance(distances: &[f64; 8], weights: &[f64; 8]) -> f64 {
2828

2929
/// Compute L1-like distance across 8 HEEL planes.
3030
///
31-
/// For each plane i: distance[i] = popcount(a[i] XOR b[i]) as f64.
31+
/// For each plane i: distance\[i\] = popcount(a\[i\] XOR b\[i\]) as f64.
3232
/// This is Hamming on binary HEEL planes — valid because HEEL planes
3333
/// ARE uniform binary data (unlike bgz17 i16 which must use L1).
3434
pub fn heel_plane_distances(a: &[u64; 8], b: &[u64; 8]) -> [f64; 8] {

‎src/hpc/amx_matmul.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl TileConfig {
8181
/// register-blocked int8 kernel: tmm0-3 = the four C accumulators, tmm4-5 =
8282
/// two plain A row-blocks (rm/unsigned), tmm6-7 = two VNNI B col-blocks
8383
/// (vvvv/signed). Every tile is 16×64 so one config serves all roles. Same
84-
/// XTILECFG layout as [`Self::for_dpbusd`]: colsb[t] u16 @ 16+2t, rows[t]
84+
/// XTILECFG layout as [`Self::for_dpbusd`]: colsb\[t\] u16 @ 16+2t, rows\[t\]
8585
/// u8 @ 48+t.
8686
///
8787
/// # Examples

‎src/hpc/amx_ops.rs‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@
3434
//!
3535
//! | tier | ops | CPUID | first silicon |
3636
//! |---|---|---|---|
37-
//! | AMX-TILE | config, zero, load/store, release | 7.0:EDX[24] | Sapphire Rapids |
38-
//! | AMX-INT8 | `tdpb{ss,su,us,uu}d` | 7.0:EDX[25] | Sapphire Rapids |
39-
//! | AMX-BF16 | `tdpbf16ps` | 7.0:EDX[22] | Sapphire Rapids |
40-
//! | AMX-FP16 | `tdpfp16ps` | 7.1:EAX[21] | Granite Rapids |
41-
//! | AMX-COMPLEX | `tcmm{im,rl}fp16ps` | 7.1:EDX[8] | Granite Rapids-D |
42-
//! | AMX-FP8 | `tdp{b,bh,hb,h}f8ps` | 1E.1:EAX[4] | Diamond Rapids |
43-
//! | AMX-TF32 | `tmmultf32ps` | 1E.1:EAX[6] | Diamond Rapids (see note) |
44-
//! | AMX-AVX512 | `tcvtrow*`, `tilemovrow` | 1E.1:EAX[7] | Diamond Rapids |
45-
//! | AMX-MOVRS | `tileloaddrs{,t1}` | 1E.1:EAX[8] | Diamond Rapids |
37+
//! | AMX-TILE | config, zero, load/store, release | 7.0:EDX\[24\] | Sapphire Rapids |
38+
//! | AMX-INT8 | `tdpb{ss,su,us,uu}d` | 7.0:EDX\[25\] | Sapphire Rapids |
39+
//! | AMX-BF16 | `tdpbf16ps` | 7.0:EDX\[22\] | Sapphire Rapids |
40+
//! | AMX-FP16 | `tdpfp16ps` | 7.1:EAX\[21\] | Granite Rapids |
41+
//! | AMX-COMPLEX | `tcmm{im,rl}fp16ps` | 7.1:EDX\[8\] | Granite Rapids-D |
42+
//! | AMX-FP8 | `tdp{b,bh,hb,h}f8ps` | 1E.1:EAX\[4\] | Diamond Rapids |
43+
//! | AMX-TF32 | `tmmultf32ps` | 1E.1:EAX\[6\] | Diamond Rapids (see note) |
44+
//! | AMX-AVX512 | `tcvtrow*`, `tilemovrow` | 1E.1:EAX\[7\] | Diamond Rapids |
45+
//! | AMX-MOVRS | `tileloaddrs{,t1}` | 1E.1:EAX\[8\] | Diamond Rapids |
4646
//!
4747
//! Note on TF32: LLVM `main` has removed `amx-tf32` (and `amx-transpose`)
4848
//! from both the assembler and `Host.cpp`. The 22.1.8 assembler in the
@@ -655,23 +655,23 @@ tile_row_to_zmm!(
655655
/// and gates the INT8 ops. This struct answers "which ops exist once I may".
656656
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
657657
pub struct AmxFeatures {
658-
/// AMX-TILE (7.0:EDX[24]).
658+
/// AMX-TILE (7.0:EDX\[24\]).
659659
pub tile: bool,
660-
/// AMX-INT8 (7.0:EDX[25]).
660+
/// AMX-INT8 (7.0:EDX\[25\]).
661661
pub int8: bool,
662-
/// AMX-BF16 (7.0:EDX[22]).
662+
/// AMX-BF16 (7.0:EDX\[22\]).
663663
pub bf16: bool,
664-
/// AMX-FP16 (7.1:EAX[21]).
664+
/// AMX-FP16 (7.1:EAX\[21\]).
665665
pub fp16: bool,
666-
/// AMX-COMPLEX (7.1:EDX[8]).
666+
/// AMX-COMPLEX (7.1:EDX\[8\]).
667667
pub complex: bool,
668-
/// AMX-FP8 (1E.1:EAX[4]).
668+
/// AMX-FP8 (1E.1:EAX\[4\]).
669669
pub fp8: bool,
670-
/// AMX-TF32 (1E.1:EAX[6]; the bit LLVM used before dropping the feature).
670+
/// AMX-TF32 (1E.1:EAX\[6\]; the bit LLVM used before dropping the feature).
671671
pub tf32: bool,
672-
/// AMX-AVX512 (1E.1:EAX[7]).
672+
/// AMX-AVX512 (1E.1:EAX\[7\]).
673673
pub avx512: bool,
674-
/// AMX-MOVRS (1E.1:EAX[8]).
674+
/// AMX-MOVRS (1E.1:EAX\[8\]).
675675
pub movrs: bool,
676676
}
677677

‎src/hpc/audio/mdct.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub const FRAME_SIZE: usize = 960;
1818
pub const MDCT_SIZE: usize = FRAME_SIZE / 2;
1919

2020
/// Sine window for MDCT (Opus uses a sine window for CELT mode).
21-
/// w[n] = sin(π/N × (n + 0.5))
21+
/// w\[n\] = sin(π/N × (n + 0.5))
2222
pub fn sine_window(n: usize) -> Vec<f32> {
2323
(0..n)
2424
.map(|i| (PI / n as f32 * (i as f32 + 0.5)).sin())

0 commit comments

Comments
 (0)