dotcom07 opened issue #14575:
Feature
Add explicit support for modelling the Zve32x, Zve32f, Zve64x, Zve64f, and Zve64d capabilities in the RISC-V backend.
RISC-V's Zve extensions provide subsets of the vector ISA for embedded processors. They differ in supported integer element widths and vector floating-point operations. Cranelift has V, Zvl, and Zvfh settings, but does not explicitly model these Zve capabilities. As noted in the discussion on #9135, the backend has largely assumed full V support.
Benefit
This would let Cranelift use the vector operations available on Zve-only embedded and edge targets, while rejecting unsupported combinations during compilation. Register size and scalar F/D support alone do not describe these targets' vector capabilities, as the following examples illustrate.
I tested this with QEMU 9.2.0 (
riscv64-linux-user). Since there are no Zve settings, I compiled withriscv64 has_v=false has_zvl128b=true has_zvfh=false, leaving scalar F/D enabled, and selected the Zve profile separately in QEMU. Both examples below compiled successfully and were linked to C harnesses that check the output values.For example, this
i64x2addition compiles even though a Zve32x target cannot use 64-bit vector elements:function %probe(i64, i64, i64) system_v { block0(v0: i64, v1: i64, v2: i64): v3 = load.i64x2 v1 v4 = load.i64x2 v2 v5 = iadd v3, v4 store v5, v0 return }Running the resulting executable with Zve32x gives SIGILL:
qemu-riscv64 -cpu rv64,v=false,zve32x=true,vlen=128,elen=32 \ -L /usr/riscv64-linux-gnu /work/bin/6feddb7954d4-add_i64x2returncode: -4 (SIGILL, as reported by Python subprocess) stdout: "" stderr: ""The same executable succeeds with
rv64,v=false,zve64x=true,vlen=128,elen=64, printingOK add_i64x2. A 128-bit register is large enough to hold the value in both configurations, but does not imply support for 64-bit elements.Similarly, scalar F/D support does not imply vector floating-point support. This
f32x4addition also compiles:function %probe(i64, i64, i64) system_v { block0(v0: i64, v1: i64, v2: i64): v3 = load.f32x4 v1 v4 = load.f32x4 v2 v5 = fadd v3, v4 store v5, v0 return }qemu-riscv64 -cpu rv64,v=false,zve32x=true,vlen=128,elen=32 \ -L /usr/riscv64-linux-gnu /work/bin/6feddb7954d4-fadd_f32x4returncode: -4 (SIGILL, as reported by Python subprocess) stdout: "" stderr: ""The same executable succeeds with
rv64,v=false,zve32f=true,vlen=128,elen=32, printingOK fadd_f32x4. Scalar F/D are enabled in both configurations; vector FP32 support is the relevant difference.These examples show constraints that need to be represented to support Zve targets; they do not assume that these configurations are already supported.
Implementation
Add Zve ISA settings and use them in the existing type and instruction predicates to distinguish register size, supported element widths, and vector FP support. Supported operations can reuse the existing vector lowering, while unsupported combinations should return a compilation error.
Instruction-specific restrictions, such as Zve64's exclusion of 64-bit high-half multiplication, also need checks. The checks should account for widths introduced internally by lowering, including extending loads, masks, and scalar/vector bitcasts. Focused code-generation tests and QEMU runs with V disabled can cover these distinctions.
Alternatives
Requiring full V for all vector code would simplify the capability checks, but exclude Zve-only hardware even for operations it supports.
alexcrichton added the cranelift:area:riscv64 label to Issue #14575.
fitzgen commented on issue #14575:
Seems like a reasonable thing to support
fitzgen added the enhancement label to Issue #14575.
Last updated: Oct 11 2026 at 04:10 UTC