darmie opened issue #14050:
Summary
aarch64lowers the signed i8 dot-product tree toSDOTunderhas_dotprod, but there is no equivalent for the mixed unsigned x signed form, which FEAT_I8MM provides asUSDOT. On an I8MM-capable part that tree currently falls back toumull/smull+saddlpwidening even though a single instruction exists.For contrast, x64 already handles the mixed form: a
VectorDot-shaped tree with an unsigned operand lowers toVPDPBUSDon 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
VPDPBUSDandUSDOTexist. 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
SDOTsupport:
- A
has_i8mmsetting inmeta/src/isa/arm64.rsalongsidehas_dotprod, with matching host detection and ause_i8mmhelper.- The
USDOTinstruction inisa/aarch64/inst.isle+ emit.- A lowering rule beside the
SDOTrule. 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/swidenpairing is what the mixed form actually produces — confirmed in disassembly (uxtlon the unsigned operand,sxtlon 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, soUSDOTwill 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
- Is the pattern above the right shape, or does the mid-end normalise the mixed tree differently than the signed one?
- Is there existing precedent for testing lowerings that need a feature the CI hosts lack?
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!
alexcrichton added the cranelift label to Issue #14050.
alexcrichton added the cranelift:area:aarch64 label to Issue #14050.
darmie closed issue #14050:
Summary
aarch64lowers the signed i8 dot-product tree toSDOTunderhas_dotprod, but there is no equivalent for the mixed unsigned x signed form, which FEAT_I8MM provides asUSDOT. On an I8MM-capable part that tree currently falls back toumull/smull+saddlpwidening even though a single instruction exists.For contrast, x64 already handles the mixed form: a
VectorDot-shaped tree with an unsigned operand lowers toVPDPBUSDon 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
VPDPBUSDandUSDOTexist. 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
SDOTsupport:
- A
has_i8mmsetting inmeta/src/isa/arm64.rsalongsidehas_dotprod, with matching host detection and ause_i8mmhelper.- The
USDOTinstruction inisa/aarch64/inst.isle+ emit.- A lowering rule beside the
SDOTrule. 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/swidenpairing is what the mixed form actually produces — confirmed in disassembly (uxtlon the unsigned operand,sxtlon 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, soUSDOTwill 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
- Is the pattern above the right shape, or does the mid-end normalise the mixed tree differently than the signed one?
- Is there existing precedent for testing lowerings that need a feature the CI hosts lack?
Last updated: Aug 30 2026 at 09:07 UTC