Repository navigation
Report a SIMD intrinsic monomorphized with a scalar instead of crashing - #4927
Merged
Merged
Conversation
`ty_validity`-style `unwrap`s in the SIMD codegen read a vector length that a scalar does not have, so `-Z autoharness` aborted the whole run on a generic helper whose type parameter carries no SIMD bound -- the shape `core_arch::simd::simd_imin` has, which blocked autoharness over the standard library. rustc rejects such a monomorphization with E0511, so no call site in a program that compiles reaches codegen this way; autoharness synthesizes the instantiation itself. Fix both ends: - One guard covers all 21 SIMD intrinsics: when the operand that must be a vector is not one, report it against the harness that reached it rather than unwrapping. `simd_splat` is the one whose vector is the return type instead of the first argument. - Autoharness rejects a candidate type that would make a SIMD intrinsic call invalid, so it picks a SIMD type where one is available and skips the function with a specific reason otherwise. Resolves model-checking#4919
Resolve the conflict with model-checking#4922's guard in `codegen_intrinsic` by keeping main's behaviour, message and issue link, with its inline list of SIMD intrinsics replaced by `Intrinsic::simd_vector_operand` (the same 21 intrinsics), which the autoharness filter shares. The test's expected message follows main's wording, which model-checking#4922's `expected/intrinsics/simd-scalar-operand` test pins. Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
…calar `E0511` (`invalid monomorphization of `simd_lt` intrinsic: expected SIMD input type, found non-SIMD `i32``) comes from rustc's codegen backends (`InvalidMonomorphization::SimdInput` in `rustc_codegen_ssa`), and type-checking the intrinsic puts no SIMD bound on its parameter. Kani replaces the backend, so an ordinary source call with a scalar does reach Kani's codegen (model-checking#4922's `simd-scalar-operand` test is one). Correct the doc comments that said such a call cannot occur in source code. Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The shared guard, candidate filtering, diagnostics, and regression coverage consistently implement the stated behavior.
Review effort: Balanced
Findings: None
What changed in this PR
Prevents autoharness from selecting scalar monomorphizations for directly called SIMD intrinsics, complementing #4922’s codegen guard.
Changes:
- Centralizes SIMD vector-operand identification.
- Filters invalid autoharness candidates while preserving the documented transitive limitation.
- Adds regression coverage for direct, transitive, and fixed-type SIMD calls.
| File | Description |
|---|---|
kani-compiler/src/intrinsics.rs |
Centralizes SIMD vector-operand selection. |
kani-compiler/src/kani_middle/codegen_units.rs |
Rejects invalid scalar SIMD candidates. |
kani-compiler/src/codegen_cprover_gotoc/codegen/intrinsic.rs |
Reuses the shared SIMD operand helper. |
tests/script-based-pre/autoharness_simd_non_simd_instantiation/simd_generic.rs |
Defines regression scenarios. |
tests/script-based-pre/autoharness_simd_non_simd_instantiation/check.sh |
Validates harness selection and completion. |
tests/script-based-pre/autoharness_simd_non_simd_instantiation/config.yml |
Registers the script-based test. |
tests/script-based-pre/autoharness_simd_non_simd_instantiation/expected |
Records expected test output. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
tautschnig
approved these changes
Oct 2, 2026
tautschnig
enabled auto-merge
October 2, 2026 13:50
Resolve the conflict with model-checking#4880 at the end of the generic instantiation search: try main's uniform `()` fallback first (it, too, goes through the SIMD check, which rejects `()` for a SIMD operand), then report a SIMD rejection, the more specific reason, ahead of model-checking#4880's attempt-limit message and the generic "no candidate type" one. Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Merged
via the queue into
model-checking:main
with commit Oct 2, 2026
5193da6
33 of 34 checks passed
This was referenced Oct 2, 2026
kasimte
pushed a commit
to kasimte/kani
that referenced
this pull request
Oct 3, 2026
…odel-checking#4951) Autoharness over the standard library still aborts on `core_arch::simd::simd_imax<T: Copy>`. After model-checking#4927 it no longer picks a scalar for `T`, but it can pick `__m128`, a SIMD type with `f32` lanes. The body stores `simd_gt`'s result in `T`, and a comparison's result is a mask that needs integer lanes, so Kani's codegen raised a compile error. A compile error aborts the whole crate, so this one function stopped every harness. It is the last compile-time blocker for the unfiltered autoharness jobs in model-checking/verify-rust-std#687 (see model-checking#4950). The fix has two parts, in the same shape as model-checking#4927: **Autoharness rejects the instantiation.** A candidate is now rejected when its body makes a SIMD comparison return anything other than an integer-lane vector with as many lanes as the operands. Autoharness then keeps searching. When an integer SIMD type also satisfies the bounds, it picks that one and the function is verified; otherwise the function is skipped with a reason that names the comparison and the lane type. **Codegen no longer aborts the crate.** An invalid comparison result type is now reported as an unsupported construct, which fails only the harnesses that reach it. This is the backstop for the case autoharness can't see: a generic function that reaches the invalid comparison one level down (model-checking#4926). **The behaviour change to weigh.** Under Kani, rustc's codegen backend never runs, so these checks are the only stand-in for rustc's `E0511`. Before this PR, a comparison written directly with an invalid result type, like `let m: f32x2 = simd_eq(x, y)`, was a compile error. Now it compiles, and verification fails if the comparison is reachable. Such a program can't be built by rustc at all, so verifying it says nothing about a real executable, but the diagnostic moves from compile time to verification time. The two tests that pinned the compile error (`simd-result-type-is-float`, `simd-cmp-result-type-is-diff-size`) now pin the unsupported check. If you'd rather keep the compile error for directly written code, the autoharness half is enough for the reported case; only the one-level-down case would still abort. **Scope.** I only changed the comparison checks. `simd_splat`, `simd_extract`, `simd_insert` and `simd_shuffle` have the same compile-error-aborts-the-crate shape, but nothing in the standard library reaches them this way today. Filed as model-checking#4952 rather than widening this PR. **Testing.** - New `tests/script-based-pre/autoharness_simd_cmp_float_lanes` checks three things: a float-only candidate is skipped with the reason; with a float and an integer type available, autoharness picks the integer one and it verifies; and the one-level-down case fails its own harness while the run completes. The test fails without the compiler change. - Locally, merged with current `main`: `expected` (498), `kani` (620), `script-based-pre` (91), `ui` (152) and `cargo-kani` (71) pass, as do fmt and clippy, both for the workspace and with `--features llbc`. - Not run with this exact branch: the full standard-library autoharness. For model-checking#4950 I ran the equivalent codegen change against verify-rust-std's `library/`, and the run completed with no panics; this branch adds the autoharness rejection on top. Resolves model-checking#4950 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
srivatsansamraj
added a commit
to srivatsansamraj/kani
that referenced
this pull request
Oct 5, 2026
A scalar instantiation of either reduction is now reported as an unsupported construct, like the other SIMD intrinsics (model-checking#4927). Before this, it crashed the compiler in `simd_size_and_type`.
srivatsansamraj
added a commit
to srivatsansamraj/kani
that referenced
this pull request
Oct 6, 2026
A scalar instantiation of either reduction is now reported as an unsupported construct, like the other SIMD intrinsics (model-checking#4927). Before this, it crashed the compiler in `simd_size_and_type`.
srivatsansamraj
added a commit
to srivatsansamraj/kani
that referenced
this pull request
Oct 9, 2026
A scalar instantiation of either reduction is now reported as an unsupported construct, like the other SIMD intrinsics (model-checking#4927). Before this, it crashed the compiler in `simd_size_and_type`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
-Z autoharnesscrashed the compiler on a generic helper whose body calls a SIMD intrinsic but whose type parameter carries no SIMD bound. Autoharness pickedT = i32, and the SIMD comparison codegen unwrapped the vector length of a scalar.core_arch::simd::simd_imin<T: Copy>has exactly this shape, socorefailed codegen, which is what blocks the unfiltered autoharness path in model-checking/verify-rust-std#687.Update after merging main: #4922 has since added the codegen guard (the crash no longer happens on main; the call is reported as an unsupported construct), so this PR is now the autoharness side of that fix: it stops autoharness from choosing such instantiations in the first place.
rustc's codegen backends reject these monomorphizations (
E0511: invalid monomorphization ofsimd_ltintrinsic: expected SIMD input type, found non-SIMDi32``), but Kani replaces the backend, so such calls reach Kani's codegen: from a harness that callsimin::<i32>directly, and from instantiations that autoharness synthesizes.Codegen. #4922's guard is kept as is (behaviour, message and issue link); its inline list of the 21 SIMD intrinsics is replaced by
Intrinsic::simd_vector_operand, which names the operand that must be a vector and lives next totry_match_simd, so a new SIMD intrinsic is added in one place and the autoharness filter below uses the same list.simd_splatis the only one whose vector is the return type rather than the first argument.Autoharness stops choosing those instantiations. A candidate type is rejected when it would make a SIMD intrinsic call in the function's own body invalid. On the reproducer this is better than skipping: autoharness moves on and picks the
#[repr(simd)]type, soiminis verified rather than reported. Where no candidate is SIMD, the function is skipped with a reason that names the intrinsic instead of blaming trait bounds the candidate does satisfy.What it deliberately leaves. A generic function that reaches the invalid instantiation one level down, through a call, is still only caught in codegen, so its harness fails rather than being skipped. Detecting that needs a transitive walk with composed substitutions, like
has_const_generic_preconditiondoes for const blocks; filed as #4926, and the new test pins the current behaviour so that fix has to update it.Testing.
tests/script-based-pre/autoharness_simd_non_simd_instantiationcovers the reproducer, the one-level-down case, and a function whose SIMD operand types are fixed (unaffected). I confirmed it fails without the fix, and that a deliberately wrong expectation fails the test. After merging main: the test, all 39script-based-preautoharness tests, theexpectedSIMD tests (including #4922'ssimd-scalar-operand) and thekaniSIMD tests pass, as do fmt and both clippy invocations. Thekani,expected,ui,cargo-kaniandscript-based-presuites pass, as do fmt and clippy.One thing worth a reviewer's eye: the candidate check calls
instance.body(), whichskip_reasonthen calls again for the chosen instance, so a generic function now costs one extra stable-MIR conversion. It happens only for candidates that already satisfy the predicates, which is normally one per function, and rustc caches the underlying monomorphization — but say if you would rather it were hoisted or pre-filtered.I could not confirm the
corecase end to end locally:simd_iminis present in the pinned toolchain's stdarch, butkani autoharness --stdfailed while buildingcompiler_builtins, before reaching any Kani code. The evidence here is that the test reproduces the same shape.Follow-up to #4922, which resolved #4919.
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.