fitzgen commented on issue #14566:
<details><summary>Full LLM report</summary>
(x >> k) << kmid-end rule emits aniconstwith a 64-bit vector type
Date 2026-10-05 Wasmtime commit 73b04cff3317d1e308866eb24359483ac6116669(main)Host macOS 15.8.1 (Darwin 24.6.0), aarch64-apple-darwinModel Claude Opus 5.5 ( claude-opus-5-5)Component cranelift/codegen/src/opts/shifts.isle(mid-end,opt_level=speed)Class Compiler panic on valid CLIF Severity Low. Wasm has no 64-bit vector types, so Wasmtime cannot reach this; other Cranelift embedders and cranelift-fuzzgencan.Summary
cranelift/codegen/src/opts/shifts.isle:27-36:(rule (simplify (ishl (fits_in_64 ty) (ushr ty x (iconst _ k)) (iconst _ k))) (let ((mask Imm64 (imm64_shl ty (imm64 0xFFFF_FFFF_FFFF_FFFF) k))) (band ty x (iconst ty mask)))) ;; ... and the same for `sshr`
fits_in_64only checksty.bits() <= 64, so it also admits the 64-bit vector
typesi8x8,i16x4andi32x2. For those the rule builds
iconst.i32x2 <mask>, which is not valid CLIF:iconstis scalar-only.What happens next depends on the verifier:
Verifier on (the default):
Verifier::iconst_bounds
(cranelift/codegen/src/verifier/mod.rs:1930-1936) hits_ => unreachable!()
instead of reporting a verifier error. Compilation panics inegraph_pass.
enable_verifier=false: the backend panics. On aarch64 the message is
no rule matched for term imm at src/isa/aarch64/inst.isle line 3737, and
riscv64 fails the same way atsrc/isa/riscv64/inst.isle line 1899.The mask would also be wrong for vectors.
imm64_shl
(isle_prelude.rs:223) masks withty.bits(), the vector's total width,
rather than the lane width.The neighbouring rule at
shifts.isle:41gets this right. It uses
(fits_in_64 (ty_int ty)), and its comment says "thisiconstmask only
works for scalar integers". These two rules date fromb9a58148cf(2023).Reproduction
All files are in this directory. Run them with the debug
clif-utilbuilt from
the audited commit.$ clif-util test repro-riscv64-none.clif # opt_level=none, riscv64 has_v: passes $ clif-util test repro-riscv64.clif # same functions at opt_level=speed thread 'worker #0' panicked at cranelift/codegen/src/verifier/mod.rs:1936:22: internal error: entered unreachable code $ clif-util test repro.clif # aarch64, speed: same verifier panic $ clif-util test repro-noverify.clif # aarch64, verifier off panicked at .../isle_aarch64.rs:7859:5: internal error: entered unreachable code: no rule matched for term imm at src/isa/aarch64/inst.isle line 3737; should it be partial? $ clif-util test optimize.clif # `; check: iconst.i32x2` passes $ clif-util test interpret.clif # reference semantics, passes: # i32x2 [0xffffffff 0x12345678] -> [0xfffffff8 0x12345678] # i16x4 [-1 5 7 0x7fff] -> [-4 4 4 0x7ffc]
repro-riscv64.clifcontains:test compile set opt_level=speed target riscv64 has_v function %f(i64) -> i64 { block0(v0: i64): v1 = bitcast.i32x2 little v0 v2 = iconst.i32 3 v3 = ushr v1, v2 v4 = ishl v3, v2 v5 = bitcast.i64 little v4 return v5 }riscv64 gives the clean before/after comparison: it compiles this function at
opt_level=noneand panics only atspeed. aarch64 cannot lower 64-bit vector
shifts even atopt_level=none.Several neighbouring cases do not fail:
- the
i32x4variant is not matched by the rule;- the other
fits_in_64rules checked (selects.isle:113-120,
icmp.isle:180,184) behave correctly on 64-bit vectors.Suggested fix
- Guard both rules with
(fits_in_64 (ty_int ty)).- Make
iconst_boundsreport a verifier error for a non-scalariconsttype
instead of hittingunreachable!(). The verifier should diagnose invalid
IR, not panic on it.</summary>
fitzgen opened issue #14566:
The rules in
opts/shifts.islethat rewrite(x >> k) << kinto
band x, (iconst ty mask)are guarded by(fits_in_64 ty). That guard also
admitsi8x8,i16x4andi32x2, so the rewrite produces an ill-typed
iconst.i32x2. The verifier then hitsunreachable!()iniconst_bounds
instead of reporting an error. With the verifier disabled, the backend
panics in ISLE.
.clifTest Casetest compile set opt_level=speed target riscv64 has_v function %f(i64) -> i64 { block0(v0: i64): v1 = bitcast.i32x2 little v0 v2 = iconst.i32 3 v3 = ushr v1, v2 v4 = ishl v3, v2 v5 = bitcast.i64 little v4 return v5 }Steps to Reproduce
clif-util test test.clifExpected Results
The function compiles, as it does with
opt_level=none.Actual Results
thread 'worker #0' panicked at cranelift/codegen/src/verifier/mod.rs:1936:22: internal error: entered unreachable codeVersions and Environment
Cranelift version or commit:
73b04cff33Operating system: macOS 15.8.1
Architecture: aarch64 (host), riscv64 (target)
fitzgen added the bug label to Issue #14566.
fitzgen added the isle label to Issue #14566.
fitzgen added the cranelift:mid-end label to Issue #14566.
cfallin closed issue #14566:
The rules in
opts/shifts.islethat rewrite(x >> k) << kinto
band x, (iconst ty mask)are guarded by(fits_in_64 ty). That guard also
admitsi8x8,i16x4andi32x2, so the rewrite produces an ill-typed
iconst.i32x2. The verifier then hitsunreachable!()iniconst_bounds
instead of reporting an error. With the verifier disabled, the backend
panics in ISLE.
.clifTest Casetest compile set opt_level=speed target riscv64 has_v function %f(i64) -> i64 { block0(v0: i64): v1 = bitcast.i32x2 little v0 v2 = iconst.i32 3 v3 = ushr v1, v2 v4 = ishl v3, v2 v5 = bitcast.i64 little v4 return v5 }Steps to Reproduce
clif-util test test.clifExpected Results
The function compiles, as it does with
opt_level=none.Actual Results
thread 'worker #0' panicked at cranelift/codegen/src/verifier/mod.rs:1936:22: internal error: entered unreachable codeVersions and Environment
Cranelift version or commit:
73b04cff33Operating system: macOS 15.8.1
Architecture: aarch64 (host), riscv64 (target)
Last updated: Oct 11 2026 at 04:10 UTC