Stream: git-wasmtime

Topic: wasmtime / issue #14050 aarch64: lower mixed unsigned x s...


view this post on Zulip Wasmtime GitHub notifications bot (Jul 31 2026 at 16:44):

darmie opened issue #14050:

Summary

aarch64 lowers the signed i8 dot-product tree to SDOT under has_dotprod, but there is no equivalent for the mixed unsigned x signed form, which FEAT_I8MM provides as USDOT. On an I8MM-capable part that tree currently falls back to umull/smull + saddlp widening even though a single instruction exists.

For contrast, x64 already handles the mixed form: a VectorDot-shaped tree with an unsigned operand lowers to VPDPBUSD on a VNNI host. The aarch64 side has the signed case only.

Background

Quantized inference kernels are overwhelmingly unsigned activations x signed weights (u8 x i8) — that asymmetry is why VPDPBUSD and USDOT exist. So this is the shape that matters most for int8 inference, and it is the one currently left on the fallback path.

I hit this lowering a quantized int8 dot kernel: on x86 with VNNI it reaches vpdpbusd, while the same kernel on aarch64 emits the widening sequence.

Proposal

Mirror the existing SDOT support:

  1. A has_i8mm setting in meta/src/isa/arm64.rs alongside has_dotprod, with matching host detection and a use_i8mm helper.
  2. The USDOT instruction in isa/aarch64/inst.isle + emit.
  3. A lowering rule beside the SDOT rule. The tree is identical except one operand widens unsigned:
(rule 8 (lower (and (use_i8mm)
                    (has_type $I32X4
                      (iadd _
                        (iadd_pairwise _
                          (iadd_pairwise _
                            (swiden_low _ lo @ (imul _ (uwiden_low _ a) (swiden_low _ b)))
                            (swiden_high _ lo))
                          (iadd_pairwise _
                            (swiden_low _ hi @ (imul _ (uwiden_high _ a) (swiden_high _ b)))
                            (swiden_high _ hi)))
                        c))))
      (usdot c a b))

The uwiden/swiden pairing is what the mixed form actually produces — confirmed in disassembly (uxtl on the unsigned operand, sxtl on the signed one).

Why an issue and not a PR

I cannot verify correctness. The machine I have is an M1, where hw.optional.arm.FEAT_I8MM = 0, so USDOT will not execute — a filetest would only prove instruction selection, not that the result is right. Given a wrong dot-product rule is a silent miscompile, that seemed like the wrong thing to submit untested.

Happy to prepare the patch if the approach looks right, and to write it against whatever the project prefers for validating I8MM lowerings (emulation, or CI hardware that has the feature).

Questions

view this post on Zulip Wasmtime GitHub notifications bot (Jul 31 2026 at 17:10):

alexcrichton commented on issue #14050:

Looking at a recent CI log I see:

Flags:                                   ... i8mm ...

so I think that this runtest will actually run in CI. This is similar to many AVX-512 lowerings we have where most of us don't have that on local machines and CI often doesn't either. Here though it looks like it'll be better where CI is running things, so feel free to send a PR!

view this post on Zulip Wasmtime GitHub notifications bot (Jul 31 2026 at 17:10):

alexcrichton added the cranelift label to Issue #14050.

view this post on Zulip Wasmtime GitHub notifications bot (Jul 31 2026 at 17:10):

alexcrichton added the cranelift:area:aarch64 label to Issue #14050.

view this post on Zulip Wasmtime GitHub notifications bot (Aug 01 2026 at 08:10):

darmie closed issue #14050:

Summary

aarch64 lowers the signed i8 dot-product tree to SDOT under has_dotprod, but there is no equivalent for the mixed unsigned x signed form, which FEAT_I8MM provides as USDOT. On an I8MM-capable part that tree currently falls back to umull/smull + saddlp widening even though a single instruction exists.

For contrast, x64 already handles the mixed form: a VectorDot-shaped tree with an unsigned operand lowers to VPDPBUSD on a VNNI host. The aarch64 side has the signed case only.

Background

Quantized inference kernels are overwhelmingly unsigned activations x signed weights (u8 x i8) — that asymmetry is why VPDPBUSD and USDOT exist. So this is the shape that matters most for int8 inference, and it is the one currently left on the fallback path.

I hit this lowering a quantized int8 dot kernel: on x86 with VNNI it reaches vpdpbusd, while the same kernel on aarch64 emits the widening sequence.

Proposal

Mirror the existing SDOT support:

  1. A has_i8mm setting in meta/src/isa/arm64.rs alongside has_dotprod, with matching host detection and a use_i8mm helper.
  2. The USDOT instruction in isa/aarch64/inst.isle + emit.
  3. A lowering rule beside the SDOT rule. The tree is identical except one operand widens unsigned:
(rule 8 (lower (and (use_i8mm)
                    (has_type $I32X4
                      (iadd _
                        (iadd_pairwise _
                          (iadd_pairwise _
                            (swiden_low _ lo @ (imul _ (uwiden_low _ a) (swiden_low _ b)))
                            (swiden_high _ lo))
                          (iadd_pairwise _
                            (swiden_low _ hi @ (imul _ (uwiden_high _ a) (swiden_high _ b)))
                            (swiden_high _ hi)))
                        c))))
      (usdot c a b))

The uwiden/swiden pairing is what the mixed form actually produces — confirmed in disassembly (uxtl on the unsigned operand, sxtl on the signed one).

Why an issue and not a PR

I cannot verify correctness. The machine I have is an M1, where hw.optional.arm.FEAT_I8MM = 0, so USDOT will not execute — a filetest would only prove instruction selection, not that the result is right. Given a wrong dot-product rule is a silent miscompile, that seemed like the wrong thing to submit untested.

Happy to prepare the patch if the approach looks right, and to write it against whatever the project prefers for validating I8MM lowerings (emulation, or CI hardware that has the feature).

Questions


Last updated: Aug 30 2026 at 09:07 UTC