fix(CI): long-running emulated rv64 matmul integration tests (#24593)
The RISCV-64 e2e matmul integration tests without the ukernels are very
long-running under QEMU emulation, and were causing timeouts in CI. This
PR disables the generic (non-uk) vectorization path for those tests
until we properly support codegen.
(Claude-generated summary)
## Summary
The RISC-V 64 e2e matmul integration tests that run **without ukernels**
(`--iree-opt-data-tiling --iree-llvmcpu-enable-ukernels=none`) are
extremely
slow under QEMU and were timing out CI (60 s per-test limit). This PR
adds
`noriscv` to all non-ukernel `dt`/`experimental_dt` matmul variants,
since the
generic vectorization path for data-tiled matmul is not yet properly
supported
on RISC-V — only the ukernel path is validated there.
**Why it's slow:** with data-tiling on but ukernels off, the packed
`mmt4d` is
lowered through generic vectorization. For the wide `M0×N0` tile it
selects
(`N0 = VLEN/8`, `M0 = 7`), the widening multiply-accumulate has no
vector×scalar
form, so the inner loop rebuilds the LHS broadcast every K-step via a
storm of
`vsetvli` reconfigurations and `vrgather`/`vslideup` permutes — e.g. for
i8 at
VLEN=256, ~118 `vsetvli` + ~19 `vrgather` per dispatch, vs ~2 `vsetvli`
and no
gathers for the ukernel. QEMU emulates every vector instruction
element-by-element, and `vsetvli`/`vrgather`/`vslide` are among the
costliest to
emulate, so the full shape set runs for tens of seconds and trips the
timeout.
`dt_i8_i32` and `experimental_dt_i8_i32` hit it first; `dt_f32_f32` was
already
at ~52 s (one slow runner from flaking).
Failing CI run:
https://github.com/iree-org/iree/actions/runs/27192246864/job/80276315195
**Emulation vs. real hardware:** the timeout is largely a QEMU artifact.
On a
SpaceMiT X60 (VLEN=256, native), the heaviest shape (540×332×516) runs
in
milliseconds — but the generic path is still 3.5–6× slower than the
ukernel
path, confirming it exercises an unsupported/unoptimized path rather
than just
an emulator quirk:
| variant (540×332×516) | 1 thread | 8 threads | generic ÷ ukernel |
|---|---|---|---|
| i8 generic | 123 ms | 37.9 ms | **6.1×** |
| i8 ukernel | 20.3 ms | 6.15 ms | — |
| f32 generic | 108 ms | 29.1 ms | **3.5×** |
| f32 ukernel | 30.9 ms | 9.08 ms | — |
(The gap is specific to the wide-`M0` tile; narrow-M shapes pick `M0=1`,
emit
clean `vwmacc.vx`, and are ~1.3×.)
Assisted-by: Claude Code
---------
Signed-off-by: Ege Beysel <beyselege@gmail.com>
diff --git a/tests/e2e/matmul/BUILD.bazel b/tests/e2e/matmul/BUILD.bazel
index 83a6ba7..0ae01d9 100644
--- a/tests/e2e/matmul/BUILD.bazel
+++ b/tests/e2e/matmul/BUILD.bazel
@@ -157,7 +157,17 @@
# f16/bf16 trigger internal LLVM assertion errors on riscv and wasm.
"noriscv",
"nowasm",
- ] if (lhs_rhs_type == "f16" or lhs_rhs_type == "bf16") else []),
+ ] if (lhs_rhs_type == "f16" or lhs_rhs_type == "bf16") else []) + ([
+ # The non-ukernel (generic-vectorized) data-tiling path is not yet
+ # optimized on RISC-V: with the large default shapes it runs for tens
+ # of seconds under the QEMU emulator and trips the e2e timeout.
+ # Skip it on RISC-V and re-add small-shape RISC-V coverage via the
+ # dedicated riscv-only rules below.
+ "noriscv",
+ ] if (not use_uk and acc_type != "f64" and lhs_rhs_type not in [
+ "f16",
+ "bf16",
+ ]) else []),
target_backends_and_drivers = [
("llvm-cpu", "local-task"),
],
@@ -311,7 +321,17 @@
# f16/bf16 trigger internal LLVM assertion errors on riscv and wasm.
"noriscv",
"nowasm",
- ] if (lhs_rhs_type == "f16" or lhs_rhs_type == "bf16") else []),
+ ] if (lhs_rhs_type == "f16" or lhs_rhs_type == "bf16") else []) + ([
+ # The non-ukernel (generic-vectorized)
+ # data-tiling path is not yet optimized on RISC-V and times out under
+ # the QEMU emulator with the large default shapes. Skip it on RISC-V
+ # here and re-add small-shape RISC-V
+ # coverage via the dedicated riscv-only rules below.
+ "noriscv",
+ ] if (not use_uk and acc_type != "f64" and lhs_rhs_type not in [
+ "f16",
+ "bf16",
+ ]) else []),
target_backends_and_drivers = [
("llvm-cpu", "local-task"),
],
@@ -358,6 +378,51 @@
]
)]
+# RISC-V only: small-shape coverage of the non-ukernel (generic-vectorized)
+# data-tiling path. That path is not yet optimized on RISC-V, so the dt /
+# experimental_dt rules above carry "noriscv" and skip RISC-V with the large
+# default shapes, would time out under the QEMU emulator.
+# These rules re-add RISC-V coverage with small shapes only; the "riscv_64:"
+# variant restricts them to RISC-V builds, so no tests are created on other
+# architectures (which keep their full large-shape coverage above). Keep the
+# type list in sync with the "noriscv" condition above; drop these once proper
+# RVV codegen for the non-ukernel path is tested.
+[iree_generated_e2e_runner_test(
+ name = "e2e_matmul_cpu_%sdt_riscv_small_%s_%s" % (
+ variant_prefix,
+ lhs_rhs_type,
+ acc_type,
+ ),
+ compiler_flags = [
+ "--iree-opt-data-tiling",
+ "--iree-llvmcpu-enable-ukernels=none",
+ ] + extra_compiler_flags,
+ generator = ":generate_e2e_matmul_tests",
+ generator_args = [
+ "--lhs_rhs_type=%s" % lhs_rhs_type,
+ "--acc_type=%s" % acc_type,
+ "--shapes=small",
+ ],
+ target_backends_and_drivers = [
+ ("llvm-cpu", "local-task"),
+ ],
+ # The riscv_64: prefix enables this variant only on RISC-V builds; the
+ # actual RVV cpu features are supplied by the toolchain's default test
+ # flags, so the features listed here are only a label.
+ target_cpu_features_variants = ["riscv_64:rvv:+v,+zvl512b"],
+ test_runner = "//tools/testing/e2e:iree-e2e-matmul-test",
+ test_type = "matmul",
+) for (variant_prefix, extra_compiler_flags) in [
+ ("", []),
+ (
+ "experimental_",
+ ["--iree-global-opt-enable-early-materialization=false"],
+ ),
+] for (lhs_rhs_type, acc_type) in [
+ ("i8", "i32"),
+ ("f32", "f32"),
+]]
+
[iree_generated_e2e_runner_test(
name = "e2e_matmul_vmvx_experimental_dt%s_%s_%s" % (
("_uk" if use_uk else ""),
diff --git a/tests/e2e/matmul/CMakeLists.txt b/tests/e2e/matmul/CMakeLists.txt
index 23dc987..58b4c09 100644
--- a/tests/e2e/matmul/CMakeLists.txt
+++ b/tests/e2e/matmul/CMakeLists.txt
@@ -138,7 +138,7 @@
"--iree-opt-data-tiling"
"--iree-llvmcpu-enable-ukernels=none"
LABELS
-
+ "noriscv"
TARGET_CPU_FEATURES_VARIANTS
"generic"
"arm_64:dotprod:+dotprod"
@@ -166,7 +166,7 @@
"--iree-opt-data-tiling"
"--iree-llvmcpu-enable-ukernels=none"
LABELS
-
+ "noriscv"
TARGET_CPU_FEATURES_VARIANTS
"generic"
"x86_64:avx2:+avx,+avx2,+fma,+f16c"
@@ -761,7 +761,7 @@
"--iree-global-opt-enable-early-materialization=false"
"--iree-llvmcpu-enable-ukernels=none"
LABELS
-
+ "noriscv"
TARGET_CPU_FEATURES_VARIANTS
"generic"
"arm_64:dotprod:+dotprod"
@@ -790,7 +790,7 @@
"--iree-global-opt-enable-early-materialization=false"
"--iree-llvmcpu-enable-ukernels=none"
LABELS
-
+ "noriscv"
TARGET_CPU_FEATURES_VARIANTS
"generic"
"x86_64:avx2:+avx,+avx2,+fma,+f16c"
@@ -1100,6 +1100,104 @@
iree_generated_e2e_runner_test(
NAME
+ e2e_matmul_cpu_dt_riscv_small_i8_i32
+ TEST_TYPE
+ matmul
+ GENERATOR
+ "generate_e2e_matmul_tests.py"
+ GENERATOR_ARGS
+ "--lhs_rhs_type=i8"
+ "--acc_type=i32"
+ "--shapes=small"
+ TEST_RUNNER
+ iree_tools_testing_e2e_iree-e2e-matmul-test
+ TARGET_BACKENDS
+ "llvm-cpu"
+ DRIVERS
+ "local-task"
+ COMPILER_FLAGS
+ "--iree-opt-data-tiling"
+ "--iree-llvmcpu-enable-ukernels=none"
+ TARGET_CPU_FEATURES_VARIANTS
+ "riscv_64:rvv:+v,+zvl512b"
+)
+
+iree_generated_e2e_runner_test(
+ NAME
+ e2e_matmul_cpu_dt_riscv_small_f32_f32
+ TEST_TYPE
+ matmul
+ GENERATOR
+ "generate_e2e_matmul_tests.py"
+ GENERATOR_ARGS
+ "--lhs_rhs_type=f32"
+ "--acc_type=f32"
+ "--shapes=small"
+ TEST_RUNNER
+ iree_tools_testing_e2e_iree-e2e-matmul-test
+ TARGET_BACKENDS
+ "llvm-cpu"
+ DRIVERS
+ "local-task"
+ COMPILER_FLAGS
+ "--iree-opt-data-tiling"
+ "--iree-llvmcpu-enable-ukernels=none"
+ TARGET_CPU_FEATURES_VARIANTS
+ "riscv_64:rvv:+v,+zvl512b"
+)
+
+iree_generated_e2e_runner_test(
+ NAME
+ e2e_matmul_cpu_experimental_dt_riscv_small_i8_i32
+ TEST_TYPE
+ matmul
+ GENERATOR
+ "generate_e2e_matmul_tests.py"
+ GENERATOR_ARGS
+ "--lhs_rhs_type=i8"
+ "--acc_type=i32"
+ "--shapes=small"
+ TEST_RUNNER
+ iree_tools_testing_e2e_iree-e2e-matmul-test
+ TARGET_BACKENDS
+ "llvm-cpu"
+ DRIVERS
+ "local-task"
+ COMPILER_FLAGS
+ "--iree-opt-data-tiling"
+ "--iree-llvmcpu-enable-ukernels=none"
+ "--iree-global-opt-enable-early-materialization=false"
+ TARGET_CPU_FEATURES_VARIANTS
+ "riscv_64:rvv:+v,+zvl512b"
+)
+
+iree_generated_e2e_runner_test(
+ NAME
+ e2e_matmul_cpu_experimental_dt_riscv_small_f32_f32
+ TEST_TYPE
+ matmul
+ GENERATOR
+ "generate_e2e_matmul_tests.py"
+ GENERATOR_ARGS
+ "--lhs_rhs_type=f32"
+ "--acc_type=f32"
+ "--shapes=small"
+ TEST_RUNNER
+ iree_tools_testing_e2e_iree-e2e-matmul-test
+ TARGET_BACKENDS
+ "llvm-cpu"
+ DRIVERS
+ "local-task"
+ COMPILER_FLAGS
+ "--iree-opt-data-tiling"
+ "--iree-llvmcpu-enable-ukernels=none"
+ "--iree-global-opt-enable-early-materialization=false"
+ TARGET_CPU_FEATURES_VARIANTS
+ "riscv_64:rvv:+v,+zvl512b"
+)
+
+iree_generated_e2e_runner_test(
+ NAME
e2e_matmul_vmvx_experimental_dt_f32_f32
TEST_TYPE
matmul