Skip to content

Make oxifft compile on stable Rust (rust-lang/rust#44839)#2

Merged
cool-japan merged 2 commits into
cool-japan:masterfrom
bjoernbethge:avx512-feature-gate
May 22, 2026
Merged

Make oxifft compile on stable Rust (rust-lang/rust#44839)#2
cool-japan merged 2 commits into
cool-japan:masterfrom
bjoernbethge:avx512-feature-gate

Conversation

@bjoernbethge
Copy link
Copy Markdown
Contributor

Why

As of rustc 1.95.0 stable (2026-04-14) and 1.97.0-nightly (2026-05-05), the function-attribute form #[target_feature(enable = "avx512f")] (and friends: avx512bw, avx512dq, avx512vl) is still gated behind the unstable feature stdarch_x86_avx512, tracked in rust-lang/rust#44839.

A crate that uses these attributes without #![feature(stdarch_x86_avx512)] fails to compile on every current toolchain — both stable and nightly. That blocks any downstream consumer of oxifft 0.3.x from building on stable rustc; the published crate currently errors out with:

error[E0658]: the target feature `avx512f` is currently unstable
   --> oxifft/src/dft/codelets/hand_avx512.rs:...
    |
    | #[target_feature(enable = "avx512f")]
    |                  ^^^^^^^^^^^^^^^^^^

What

Patch 1/2 (oxifft) adds a default-off avx512 = [] Cargo feature and gates every AVX-512 attribute, dispatcher arm, and module declaration (hand_avx512, hand_avx512_twiddles, simd::avx512) behind it. The if/else if chain in stockham::stockham_f64 is split so the AVX-2 fallback remains a complete cascade when AVX-512 is feature-gated out.

Patch 2/2 (oxifft-codegen-impl) does the analogous thing inside the proc-macro emitters: every quote! block that emits #[target_feature(enable = "avx512f")] is wrapped with #[cfg(feature = "avx512")], and the runtime dispatch arms emitted into the consumer crate (under gen_simd::mod and gen_simd::runtime_dispatch) are gated identically.

The emitted #[cfg(feature = "avx512")] attribute references the consumer crate's feature, so oxifft and oxifft-codegen-impl move together: enabling oxifft/avx512 (on nightly with the appropriate #![feature(stdarch_x86_avx512)]) restores the full pre-patch behaviour end-to-end.

No API or ABI change. The patches preserve every public type, function and re-export. Once Rust stabilises the AVX-512 target_feature attribute, these gates can be removed and the feature flipped to default-on.

Verification

  • cargo build --workspace on rustc 1.95.0 stable, x86_64-pc-windows-msvc: finishes in ~30 s with zero compiler warnings.
  • cargo build --workspace --release: clean, zero warnings.
  • cargo clippy -p oxifft -p oxifft-codegen-impl: no new lints introduced; all clippy warnings present are pre-existing in unmodified files (kernel/twiddle, simd_butterfly, complex_mul, api/plan/types, codelets/simd/small_sizes).

I haven't verified the --features avx512 path because that requires a nightly with stdarch_x86_avx512 and a consumer that opts in; if you want me to run that smoke-test before merging please point me at the right invocation.

Companion patches

Equivalent fixes for the cascading AVX-512 issue exist for oxiblas (oxiblas-core + oxiblas-blas) and scirs (scirs2-core + scirs2-fft + scirs2-linalg). I'll submit them in their own PRs once this lands (or earlier if you'd like to discuss the cross-repo coordination — happy to open an issue first).

rustc 1.95 stable / 1.97 nightly still treat
`#[target_feature(enable = "avx512*")]` as unstable
(rust-lang/rust#44839). This commit makes the crate compile on stable
Rust without losing AVX-512 capability for nightly users who opt in.

Changes:
* Add default-off `avx512` Cargo feature.
* Gate every `#[target_feature(enable = "avx512*")]` attribute and
  matching dispatcher arm with `#[cfg(feature = "avx512")]`.
* Split `if/else if` chains where AVX-512 was the head, so AVX-2 / SSE
  / scalar fallbacks remain a complete cascade when the feature is off.

No API or ABI change when `--features avx512` is enabled.

Tested with `cargo build --workspace` on rustc 1.95.0 stable,
x86_64-pc-windows-msvc — workspace builds clean with zero warnings.

Signed-off-by: Bjorn Bethge <8515720+bjoernbethge@users.noreply.github.com>
rustc 1.95 stable / 1.97 nightly still treat
`#[target_feature(enable = "avx512*")]` as unstable
(rust-lang/rust#44839). The proc-macro emitters in `gen_simd::avx512`
generate code that carries this attribute unconditionally, which means
every consumer crate (most notably `oxifft`) inherits the build break.

Changes:
* Wrap each emitted `#[target_feature(enable = "avx512f")]` in a
  `#[cfg(feature = "avx512")]` inside the `quote!` block.
* Wrap the runtime AVX-512 dispatch arm in `gen_dispatcher` and the
  cached-dispatcher emission with `#[cfg(feature = "avx512")]`.
* Wrap the AVX-512 detection arm in `build_detect_x86_body` with the
  same gate.

The emitted code references the consumer crate's `feature = "avx512"`
flag, so this works in concert with a matching feature in `oxifft`.

No API change. Without the consumer-side `avx512` feature, the
generated dispatchers fall through to the existing AVX-2 / SSE / scalar
paths.

Signed-off-by: Bjorn Bethge <8515720+bjoernbethge@users.noreply.github.com>
@cool-japan cool-japan merged commit 7e21ad5 into cool-japan:master May 22, 2026
@bjoernbethge
Copy link
Copy Markdown
Contributor Author

Follow-up — I have to correct this PR. The diagnosis behind it was wrong, and I'm sorry.

After the merge I re-checked on a clean toolchain. My "Verification" claim above was never actually run against rustc 1.95.0 — my machine had a separate Rust stable MSVC 1.88 installation ahead of the rustup proxy on PATH, so every cargo build I reported (including the one I labelled "rustc 1.95.0 stable") in fact used rustc 1.88.0 from June 2025.

I have now verified properly. Building the unmodified, pre-PR v0.3.1 tag with cargo build --workspace on rustc 1.95.0:

Finished `dev` profile [unoptimized + debuginfo] target(s) in 32.10s

Zero errors. The error[E0658] quoted in this PR's description only occurs on rustc ≤ 1.88.

The reason: #[target_feature(enable = "avx512f")] was stabilized in rustc 1.89 (rust-lang/rust#138940), and the _mm512_* intrinsics in stdarch shortly after. oxifft 0.3.x compiles fine on stable rustc 1.89 or newer — no feature gate needed.

Consequence of the merge: avx512 is now a default-off feature, so a default cargo build of 0.3.2 no longer compiles the AVX-512 codepaths. On AVX-512 hardware with a current rustc that's a silent performance regression versus 0.3.1 — the runtime dispatcher has no AVX-512 arm left to select.

The only population genuinely affected by the original (non-)problem is anyone pinned to rustc ≤ 1.88. For them the right fix is a documented MSRV of 1.89, not making AVX-512 opt-in for everyone else.

Possible resolutions — entirely your call:

  1. Revert this PR (and yank/repoint 0.3.2) — restores 0.3.1 behaviour.
  2. Keep the avx512 feature but flip it default-on and document an MSRV of 1.89.

I'm happy to open whichever PR you prefer, or none if you'd rather handle it yourself. Apologies again — this was my mistake, and the verification line I wrote was not something I had actually done.

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.

2 participants