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