Who is this for?

This is an advanced topic for developers who want to efficiently decode packed low-bit weights inside a Scalable Matrix Extension 2 (SME2) matrix multiplication kernel with lookup-table instructions (LUTIs).

What will you learn?

Upon completion of this Learning Path, you will be able to:

  • Understand how LUTI2 expands packed 2-bit indices into arithmetic-ready values.
  • Compare equivalent low-bit decode paths implemented with plain C and SME2 LUTI2.
  • Validate the implementations against a scalar reference and inspect the generated SME2 instructions.
  • Apply a repeatable workflow for programming SME2 LUTI.

Prerequisites

Before starting, you will need the following:

  • Familiarity with C, AArch64 assembly, quantization, and matrix multiplication
  • Understanding of SME2 streaming mode and ZA storage; for more information, see Accelerate matrix multiplication performance with SME2
  • A Mac system with Apple silicon (M4 or later), or an Android device with SME2 support
  • Make, wget, and LLVM Clang 22 or later for native macOS builds
  • For Android builds, a macOS or Linux build host with LLVM Clang 22 or later and Android NDK r29
  • For Android execution, an Android 15 or later device with SME2

Summary

AI-assisted

This summary was drafted with an approved AI-assisted workflow and reviewed by Arm contributors before publication. Human technical review remains part of the process so the final page reflects engineering rigor, accuracy, and Arm editorial standards.

Close
?
You’ll decode packed 2-bit and 4-bit weight indices with Arm SME2 LUTI2 and LUTI4, then validate the results against plain C references. First, you’ll learn how LUTI expands low-bit codes through ZT0, Z registers, and ZA. Next, you’ll configure a macOS or Android environment and compare LUTI2 with scalar decoding. Finally, you’ll apply a four-step programming method to LUTI4 and chained LUTI4-to-LUTI2 examples, then examine additional LUTI feature paths.

Frequently asked questions

AI-assisted

These FAQs were drafted with an approved AI-assisted workflow and reviewed by Arm contributors before publication. Human technical review remains part of the process so the final page reflects engineering rigor, accuracy, and Arm editorial standards.

Close
?
How do I choose between running natively on my Mac and cross-compiling for my Android device?
Run natively on an arm64 macOS system with Apple silicon M4 or later, or cross-compile on macOS or Linux and run on an Android phone with SME2 support. Use LLVM Clang 22 or later in both cases, and use Android NDK r29 when targeting Android.
What result should I expect when I compare the plain C and SME2 paths?
You should see PASS: LUTI2 SME2 matches plain C matmul. after the program compares the matrices element by element. If the device prints SKIP: No support for SME2 on this device., you haven’t validated the calculation, but you can still inspect the generated instructions on the build host.
Where does SME2 store the LUT that I reference with LUTI?
In the original SME2 forms used by the runnable examples, you load the lookup table into the fixed 512-bit ZT0 register. LUTI2 and LUTI4 then use packed indices from source Z registers to select table entries. With FEAT_LUT, you can instead use one or two scalable Z registers as the table source.
When should I use LUTI2 versus LUTI4 in my code?
Use LUTI2 for 2-bit packed indices and LUTI4 for 4-bit packed indices. You can use LUTI4 with FMOPA, or chain LUTI4 and LUTI2 before SDOT.
How do I check that the compiler generated LUTI and the expected SME2 instructions?
Run make disassemble-example-1 for the native macOS executable or make disassemble-example-1-android for the Android executable. Confirm that the output contains one LUTI2 instruction followed by four SMOPA instructions that target ZA0 through ZA3. You can disassemble either executable without SME2 hardware.
Next