Cover image for ARM SVE/SVE2

ARM SVE/SVE2

Words 2.5k
Views
Visitors
Timeline

Timeline

2025-10-30

init

This article introduces the ARM SVE/SVE2 scalable vector instruction set. SVE is a new generation SIMD instruction set for high-performance computing and machine learning, not a simple extension of NEON. Its core is the variable vector length programming model (VLA). The article details the SVE register structure, including 32 variable-length vector registers Z0~Z31, 16 predicate registers P0~P15, the First-Fault Register FFR, and the control register ZCR_ELx. It also explains four unique programming modes: predicate-based predicated instructions (merging/zeroing predication), gather loads and scatter stores, predicate-based loop control (such as WHILELO, INCB, BRKA instructions and PSTATE/NZCV flag updates), and software speculation-based vector partitioning (handling exceptions via FFR and LDFF1B). In addition, it introduces SVE instruction syntax, experimental environments (such as QEMU), and an example of implementing memcpy using SVE.

Reference documents:

SVE

Scalable Vector Extension

  • SVE-related manuals:
    • 《ARM Architecture Reference Manual Supplement, The Scalable Vector Extension》
    • 《ARM A64 Instruction Set Architecture ARMv9, for Armv9-A architecture profile》

Scalable Vector Instructions SVE/SVE2

  • SVE stands for Scalable Vector Extension
  • The first version was added in ARMv8.2, and the second version was added in ARMv9.
  • SVE is a brand-new vector instruction set developed for high-performance computing (HPC) and machine learning. It is a next-generation SIMD instruction set implementation, andnot a simple extension of the NEON instruction set.
  • Many concepts in the SVE instruction set are similar to those in the NEON instruction set, such as vectors, lanes, data elements, etc.
  • SVE introduces a brand-new concept:Variable Vector Length programming model (Vector Length Agnostic,VLA)

SVE registers

  • 32 new variable-length vector registers Z0~Z31
  • 16 predicate registers P0~P15
  • First-Fault Register (FFR)
  • SVE control register ZCR_ELx

Set vector register length

Register typesNameNumberEach register lengthDescription
Z registersZ0–Z3132VL bitsVector data registers
P registersP0–P1516VL / 8 bitsPredicate registers (mask)
FFRFFR1VL / 8 bitsFirst-Fault Register (FFR), predicate type

The vector length is calledvector length

Variable-length vector register

Variable-length vector register
Variable-length vector register

Predicate register

Predicate register
Predicate register

SVE instruction syntax

  • The SVE instruction format consists of an opcode, destination register, P register, and input operands.
1
LD1D {<Zt>.D}, <Pg>/Z, [<Xn|SP>, <Xm>, LSL #3]
1
ADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>

SVE experimental environment

Early Cortex-A cores

  • Cortex-A53 / A55 / A57 / A72
    • only supports NEON(128-bit SIMD), does not support SVE or SVE2

QEMU

123456789101112
qemu-system-aarch64 -m 1024 -cpu max,sve=on,sve256=on -M virt,gic-version=3,its=on,iommu=smmuv3\			-nographic $SMP -kernel arch/arm64/boot/Image \			-append \"$kernel_arg $debug_arg $rootfs_arg $crash_arg $dyn_arg\"\			-drive if=none,file=$rootfs_image,id=hd0\			-device virtio-blk-device,drive=hd0\			--fsdev local,id=kmod_dev,path=./kmodules,security_model=none\			-device virtio-9p-pci,fsdev=kmod_dev,mount_tag=kmod_mount\			$DBG"# Compile, note that the -march=armv8-a+sve parameter must be added.gcc -g -march=armv8-a+sve -o hello hello_sve.S

SVE instructions
SVE instructions

SVE-specific programming mode 1: Predicated instructions

  • The SVE instruction set provides a predication management mechanism (governing predicate) to support variable-length vector computation.
  • Predicated instructions use the predication management mechanism to determine which data elements in the vector register are active. In predicated instructions, only these active data elements are processed; inactive data elements are not processed.
  • Example:

Governing predicate
Governing predicate

Merging predication and zeroing predication

  • Zeroing predication: In the destination vector register, the values of inactive data elements are filled with 0.
  • Merging predication: In the destination vector register, inactive data elements retain their original values.

Zeroing predication

Zeroing predication
Zeroing predication

Merging predication

Merging predication
Merging predication

SVE-specific programming mode 2: Gather-load and scatter-store

  • Supports gather-load and scatter-store modes.
  • Gather loads and scatter stores refer to the ability toUse the value of each lane in a vector register as a base address or offset to implement load and store of non-contiguous addresses.
  • The traditional NEON instruction set can only support linear address load and store operations.

Example: gather load, loading values from multiple scattered addresses.

Gather load, loading values from multiple scattered addresses.
Gather load, loading values from multiple scattered addresses.

Example: scatter store, storing values to multiple scattered addresses.

Scatter store
Scatter store

SVE-specific programming pattern 3: Predicate-based loop control

  • WithPredicate register PninActive data elements as the object to implement loop control.
  • PSTATE and NZCV status flags
  • The SVE instruction set provides the following groups of instructions related to loop control.
    • Instructions for initializing predicate registers, such as WHILELO, etc.
    • Instructions for incrementing the count of data elements based on predicate constraints, such as INCB, etc.
    • Instructions that combine with branch instructions according to SVE condition opcodes to perform conditional branching, such as B.FIRST, etc.
    • Comparison instructions based on data elements as objects, such as CMPEQ, etc.
    • Loop exit instructions, such as BRKA.

PSTATE processor state and NZCV

  • The loop control method based on data elements can be organically combined with the processor state PSTATE.
    • When SVE generates a predicate result, it updates the NZCV status flags of PSTATE.
    • SVE instructions update the NZCV status flags of PSTATE based on the results of predicate registers or the FFR register.
    • SVE instructions can also update the NZCV status flags of PSTATE based on the CTERMEQ/CTERMNE instructions.

Processor status flags and SVE
Processor status flags and SVE

Predicate register initialization instructions

Similar to a C while loop, given an initial value and a target value, using the number of data elements contained in a vector register as the step size, then traversing in an increasing or decreasing manner to initialize the data elements in the predicate register.

Predicate register initialization instructions
Predicate register initialization instructions

Using whilelt as an example

1
whilelt  <pd>.<T>, <Rn>, <Rm>
  • <pd>: destination predicate register (e.g., p0, p1)
  • <T>: element type (e.g., .b, .h, .s, .d)
  • <Rn>: starting index or count register
  • <Rm>: ending index or upper limit register
1
p[i] = (Rn + i < Rm) ? 1 : 0
  • Starting from Rn, compare indices element by element;
  • As long as the current index is still ‘less than Rm’, set the correspondingpbit to 1;
  • Once it exceeds, set to 0.
TypeElement bit widthIncrement per step (bytes)Example
.b8-bit11-byte alignment
.h16-bit22-byte alignment
.s32-bit44-byte aligned
.d64-bit88-byte alignment

Example

1
whilelt p0.b, xzr, x2
  • In p0.b.bIndicates the element (lane) bit width is 8 bits
  • xzr is the starting value (0)
  • x2 is the target upper limit. Fill from low to high in increasing order until reaching x2 or all elements in the predicate register have been initialized.

SVE condition opcode

SVE condition opcode
SVE condition opcode

Increment the statistical count of data elements based on the predicate constraint

Increment the statistical count of data elements
Increment the statistical count of data elements

Comparison instructions based on data elements as objects

Comparison instructions based on data elements as objects
Comparison instructions based on data elements as objects

Break loop instruction

  • BRKA instruction
1
BRKA <Pd>.B, <Pg>/<ZM>, <Pn>.B

break after

BRKA instruction
BRKA instruction

  • BRKB instruction
1
BRKB <Pd>.B, <Pg>/<ZM>, <Pn>.B

BRKB instruction
BRKB instruction

Experiment 2: Implement the memcpy_1b() function using SVE instructions

Experiment 2
Experiment 2

123456789101112131415161718
.global sve_ld1_test// x0 = dest// x1 = src// x2 = sizesve_ld1_test:	mov x3, #0	// p0[i] = ((x3 + i) < x2) ? 1 : 0	whilelt p0.b, x3, x21:	// Use /z to avoid garbage values; all unloaded elements become 0	ld1b {z0.b}, p0/z, [x1, x3]	// Write all; /z is not needed	st1b {z0.b}, p0, [x0, x3]	incb x3	whilelt p0.b, x3, x2	b.any 1b		ret

AssumeVLIf it is 256, then p0 can contain at most 32 8-bit (B) elements; incb x3 increases x3 by the byte count corresponding to VL, i.e., from 0 to 32 (32 bytes).

The instruction whilelt p0.b, x3, x2: when x3=32, p0.b is all zeros.

b.any means the branch is taken as long as any element in the predicate register is active.

Experiment 3: Implement the memcpy_4b() function using SVE instructions

Experiment 3
Experiment 3

12345678910111213
.global sve_ld1_testsve_ld1_test:	lsr x2, x2, 2	mov x3, #0	whilelt p0.s, x3, x21:	ld1w {z0.s}, p0/z, [x1, x3, lsl 2]	st1w {z0.s}, p0, [x0, x3, lsl 2]	incw x3	whilelt p0.s, x3, x2	b.any 1b		ret

Procedure
Procedure

SVE-specific programming pattern 4: Vector partitioning based on software speculation

  • NEON does not support speculative load operations; SVE does.
  • The challenge with speculative load operations: if some elements cause a memory fault or access an invalid page during the read, it may be difficult to track which lane’s data read operation caused it.
  • SVE introduces:
    • First-Fault Register (FFR)
    • First-fault load instructions, for exampleLDFF1B

Example:

1
LDFF1D Z0.D, P0/Z, [Z1.D]

Use the value in each lane of the Z1.D register as an address to load the element at the corresponding address into Z0.

Use the value in each lane of the Z1.D register as an address to load the element at the corresponding address into Z0.
Use the value in each lane of the Z1.D register as an address to load the element at the corresponding address into Z0.

The third lane is an invalid address; it is directly marked as a load failure without reporting to the CPU.

SVE/SVE2 instructions

  • SVE was added in ARMv8.2, and SVE2 was added in ARMv9
  • SVE/SVE2 instruction manual: “ARM A64 Instruction Set Architecture ARMv9, for Armv9-A architecture profile”
  • The SVE instruction set contains hundreds of instructions, which can be divided into the following major categories
    • Load/store instructions and prefetch instructions
    • Vector move instructions
    • Integer arithmetic instructions
    • Bit manipulation instructions
    • Floating-point arithmetic instructions
    • Predicate operation instructions
    • Data element operation instructions
  • How to read the instruction manual:

Three types
Three types

Experiment 4: Case Study 1 - Using SVE instructions to optimize the strcmp function

Experiment 4
Experiment 4

  • There are two difficulties in using SVE instructions to optimize strcmp():
    • Difficulty 1: The lengths of strings str1 and str2 are unknown. In C, the end of a string is determined by checking whether the character is ‘\0’. In vector operations, SVE load instructions load data from multiple lanes at once. If data beyond the end of the string is loaded, it will cause an illegal access and lead to program errors.
    • Difficulty 2: The tail problem
123456789101112131415161718192021222324252627282930313233343536373839404142
.global strcmp_svestrcmp_sve:    ptrue p5.b                       // p5 = all-ones predicate register (with byte as the element size), used to indicate 'process all byte lanes'    setffr                           // Initialize / clear the First-Fault Register (FFR) to prepare for fault-first loads    mov x5, #0                       // x5 = byte offset index (starting from 0), used for offsetting the two stringsl_loop:    ldff1b z0.b, p5/z, [x0, x5]      // Perform a fault-first byte load from (x0 + x5) into z0 (according to p5 lanes)                                     // If a fault such as an illegal access occurs, the FFR records the lanes that were successfully loaded    ldff1b z1.b, p5/z, [x1, x5]      // Similarly, load from (x1 + x5) into z1 (using fault-first as above)    rdffrs p7.b, p5/z                // Read and clear the FFR, write the 'mask of successfully loaded lanes' into p7 (according to p5 lanes),                                     // so that we know how many lanes the two ldff1b instructions above actually loaded successfully (if there is no fault, p7==p5)    b.nlast l_fault                  // If it is not the last block (i.e., a fault occurred / only some lanes were loaded), jump to l_fault to handle the partial load                                     // That is, if the load is interrupted/partially completed, the fault handling path needs to be taken.    incb x5                          // x5 += VL_bytes (increase offset by SVE's current vector length), prepare for the next full vector block.    cmpeq p0.b, p5/z, z0.b, #0       // p0[i] = (z0[i] == 0) — detect whether a NUL byte appears in s1.    cmpne p1.b, p5/z, z0.b, z1.b     // p1[i] = (z0[i] != z1[i]) — detect whether the two string bytes differ.l_test:    orrs p4.b, p5/z, p0.b, p1.b      // p4 = p0 OR p1; orrs also updates the integer condition flags (NZ) for subsequent branches.                                     // p4 indicates 'the termination condition (NUL or inequality) has been reached on this lane'.    b.none l_loop                    // If no bit in p4 is true (i.e., none true), continue the loop to load the next vector block.l_return:    brkb p4.b, p5/z, p4.b            //  The purpose here is to process p4 into a form that makes it easy to extract the 'first occurrence position'.                                     // A common approach is to place the bit to be extracted (the first true bit in the current block) into the last bit of the vector.                                     // This allows the subsequent lasta instruction to directly extract the corresponding byte from that bit.                                         lasta w0, p4, z0.b               // Extract the byte located by brkb from z0 into w0 (extracted into a 32-bit register).                                     // lasta extracts the corresponding element value based on the 'last active bit' of p4 (zero-extended / or unsigned extended).    lasta w1, p4, z1.b               // Same as above, extract the corresponding byte from z1 into w1.    sub w0, w0, w1                   // Compute the difference w0 = (byte_from_z0) - (byte_from_z1), as the return value of strcmp.    ret                              // Return (return value is in w0).l_fault:    incp x5, p7.b                    // x5 += the number of bytes successfully loaded (the number of true bits indicated by p7, in bytes).                                     // Thus x5 points to the position to continue processing next (the already processed part does not need to be read again).    setffr                           // Reinitialize/clear FFR to prepare for the next fault-first load.    cmpeq p0.b, p7/z, z0.b, #0       // On the lanes that were just successfully loaded, compare whether z0 is 0 (valid only on the lanes indicated by p7).    cmpne p1.b, p7/z, z0.b, z1.b     // On the lanes that were just successfully loaded, compare whether z0 and z1 are unequal.    b l_test                         // Jump back to the unified termination check (l_test will do the OR and decide whether to continue or go to the return path).

Procedure
Procedure

Case 5: RGB24 to BGR24

Case 5
Case 5

Case 6: 4×4 Product Matrix

Case 6
Case 6

Case 6
Case 6

Differences from Neon Instructions

Differences from Neon Instructions
Differences from Neon Instructions

Differences from Neon Instructions
Differences from Neon Instructions

Summary: SVE Instructions Used Above

  • whilelt/whilelo Instructions
  • b.Any Branch Instructions
  • BRKA and BRKB Instructions
  • LASTA Instruction
  • LD1 and ST1 Instructions
  • LD3 and ST3 Instructions
  • FMLA Instruction
  • INCB Instructions
  • ldff1b Instructions (First-Fault Load)
  • SETFFR and RDFFRS Instructions
  • CMPEQ and CMPNE Instructions
  • MOV Instructions
Loading comments…