[Mlir-commits] [mlir] 08636d4 - [mlir][spirv] Add Arm.ExperimentalMLOperations.1 extended inst set (#202283)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Jun 9 02:46:28 PDT 2026


Author: Davide Grohmann
Date: 2026-06-09T11:46:23+02:00
New Revision: 08636d456502fb7404e632598e16f3698367a6f7

URL: https://github.com/llvm/llvm-project/commit/08636d456502fb7404e632598e16f3698367a6f7
DIFF: https://github.com/llvm/llvm-project/commit/08636d456502fb7404e632598e16f3698367a6f7.diff

LOG: [mlir][spirv] Add Arm.ExperimentalMLOperations.1 extended inst set (#202283)

This instruction set provides a mechanism to encode experimental ML
operations in SPIR-V modules. Such instructions are encoded via the
single CALL operator in the instruction set by specifying an op_code and
customized inputs values.

Reference:
https://github.com/KhronosGroup/SPIRV-Registry/blob/main/extended/Arm.ExperimentalMLOperations.asciidoc

Signed-off-by: Niklas Lithammer <niklas.lithammer at arm.com>
Signed-off-by: Davide Grohmann <davide.grohmann at arm.com>

Added: 
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVExperimentalMLOps.td
    mlir/test/Dialect/SPIRV/IR/experimental-ml-ops.mlir
    mlir/test/Target/SPIRV/experimental-ml-ops.mlir

Modified: 
    mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVExperimentalMLOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVExperimentalMLOps.td
new file mode 100644
index 0000000000000..ddd478881958b
--- /dev/null
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVExperimentalMLOps.td
@@ -0,0 +1,52 @@
+//===- SPIRVExperimentalMLOps.td - Experimental ML ops ------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_SPIRV_IR_EXPERIMENTAL_ML_OPS
+#define MLIR_DIALECT_SPIRV_IR_EXPERIMENTAL_ML_OPS
+
+include "mlir/Dialect/SPIRV/IR/SPIRVBase.td"
+
+class SPIRV_ExperimentalMLOp<string mnemonic, int opcode,
+                             list<Trait> traits = []> :
+  SPIRV_ExtInstOp<mnemonic, "ExperimentalML", "Arm.ExperimentalMLOperations.1",
+                  opcode, traits> {
+  let availability = [
+    MinVersion<SPIRV_V_1_0>,
+    MaxVersion<SPIRV_V_1_6>,
+    Extension<[]>,
+    Capability<[]>
+  ];
+
+  let hasVerifier = 0;
+}
+
+def SPIRV_ExperimentalMLCallOp : SPIRV_ExperimentalMLOp<"Call", 0> {
+  let summary = "Call an Arm experimental ML operation.";
+
+  let description = [{
+    Calls an operation encoded using the Arm.ExperimentalMLOperations extended
+    instruction set. The `opcode` attribute is serialized as the operation
+    opcode literal integer operand of CALL.
+  }];
+
+  let arguments = (ins
+    I32Attr:$opcode,
+    Variadic<AnyType>:$parameters
+  );
+
+  let results = (outs
+    AnyType:$output
+  );
+
+  let assemblyFormat = [{
+    `opcode` `=` $opcode `,`
+    $parameters attr-dict `:` functional-type($parameters, $output)
+  }];
+}
+
+#endif // MLIR_DIALECT_SPIRV_IR_EXPERIMENTAL_ML_OPS

diff  --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
index 3ef9699154cd1..14dc76aef57db 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.td
@@ -30,6 +30,7 @@ include "mlir/Dialect/SPIRV/IR/SPIRVCastOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVCompositeOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVControlFlowOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVCooperativeMatrixOps.td"
+include "mlir/Dialect/SPIRV/IR/SPIRVExperimentalMLOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVIntelExtOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVGLOps.td"
 include "mlir/Dialect/SPIRV/IR/SPIRVGraphOps.td"

diff  --git a/mlir/test/Dialect/SPIRV/IR/experimental-ml-ops.mlir b/mlir/test/Dialect/SPIRV/IR/experimental-ml-ops.mlir
new file mode 100644
index 0000000000000..caccb043d3af2
--- /dev/null
+++ b/mlir/test/Dialect/SPIRV/IR/experimental-ml-ops.mlir
@@ -0,0 +1,14 @@
+// RUN: mlir-opt %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// spirv.ExperimentalML.Call
+//===----------------------------------------------------------------------===//
+
+spirv.ARM.Graph @experimental_ml_call(%arg0: !spirv.arm.tensor<1x16xf32>, %arg1: !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32> {
+  // CHECK: %[[NAME:.*]] = spirv.Constant dense<[83, 101, 108, 102, 65, 116, 116, 101, 110, 116, 105, 111, 110, 79, 112]> : tensor<15xi8> : !spirv.array<15 x i8>
+  %name = spirv.Constant dense<[83, 101, 108, 102, 65, 116, 116, 101, 110, 116, 105, 111, 110, 79, 112]> : tensor<15xi8> : !spirv.array<15 x i8>
+  // CHECK: {{%.*}} = spirv.ExperimentalML.Call opcode = 0, %[[NAME]], %arg0, %arg1 : (!spirv.array<15 x i8>, !spirv.arm.tensor<1x16xf32>, !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32>
+  %0 = spirv.ExperimentalML.Call opcode = 0, %name, %arg0, %arg1 : (!spirv.array<15 x i8>, !spirv.arm.tensor<1x16xf32>, !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32>
+  // CHECK: spirv.ARM.GraphOutputs {{%.*}} : !spirv.arm.tensor<1x16xf32>
+  spirv.ARM.GraphOutputs %0 : !spirv.arm.tensor<1x16xf32>
+}

diff  --git a/mlir/test/Target/SPIRV/experimental-ml-ops.mlir b/mlir/test/Target/SPIRV/experimental-ml-ops.mlir
new file mode 100644
index 0000000000000..5876f7339c330
--- /dev/null
+++ b/mlir/test/Target/SPIRV/experimental-ml-ops.mlir
@@ -0,0 +1,25 @@
+// RUN: mlir-translate --no-implicit-module --test-spirv-roundtrip %s | FileCheck %s
+// RUN: %if spirv-tools %{ mlir-translate --no-implicit-module --serialize-spirv %s | spirv-val %}
+
+// CHECK: spirv.module Logical Vulkan requires
+spirv.module Logical Vulkan requires #spirv.vce<v1.3, [VulkanMemoryModel, Shader, Int8, Float16, TensorsARM, GraphARM], [SPV_ARM_tensors, SPV_ARM_graph, SPV_KHR_vulkan_memory_model]> {
+  // CHECK: spirv.GlobalVariable @main_arg_0 bind(0, 0) : !spirv.ptr<!spirv.arm.tensor<1x16xf32>, UniformConstant>
+  spirv.GlobalVariable @main_arg_0 bind(0, 0) : !spirv.ptr<!spirv.arm.tensor<1x16xf32>, UniformConstant>
+  // CHECK: spirv.GlobalVariable @main_arg_1 bind(0, 1) : !spirv.ptr<!spirv.arm.tensor<1x16xf32>, UniformConstant>
+  spirv.GlobalVariable @main_arg_1 bind(0, 1) : !spirv.ptr<!spirv.arm.tensor<1x16xf32>, UniformConstant>
+  // CHECK: spirv.GlobalVariable @main_res_0 bind(0, 2) : !spirv.ptr<!spirv.arm.tensor<1x16xf32>, UniformConstant>
+  spirv.GlobalVariable @main_res_0 bind(0, 2) : !spirv.ptr<!spirv.arm.tensor<1x16xf32>, UniformConstant>
+  // CHECK: spirv.ARM.GraphEntryPoint @main, @main_arg_0, @main_arg_1, @main_res_0
+  spirv.ARM.GraphEntryPoint @main, @main_arg_0, @main_arg_1, @main_res_0
+  // CHECK: spirv.ARM.Graph @main(%arg0: !spirv.arm.tensor<1x16xf32>, %arg1: !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32>
+  spirv.ARM.Graph @main(%arg0: !spirv.arm.tensor<1x16xf32>, %arg1: !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32> {
+    // CHECK: %[[NAME:.*]] = spirv.Constant [83 : i8, 101 : i8, 108 : i8, 102 : i8, 65 : i8, 116 : i8, 116 : i8, 101 : i8, 110 : i8, 116 : i8, 105 : i8, 111 : i8, 110 : i8, 79 : i8, 112 : i8] : !spirv.array<15 x i8>
+    %name = spirv.Constant dense<[83, 101, 108, 102, 65, 116, 116, 101, 110, 116, 105, 111, 110, 79, 112]> : tensor<15xi8> : !spirv.array<15 x i8>
+    // CHECK: %[[ATTRS:.*]] = spirv.Constant [123 : i8, 34 : i8, 111 : i8, 112 : i8, 101 : i8, 114 : i8, 97 : i8, 116 : i8, 111 : i8, 114 : i8, 95 : i8, 110 : i8, 97 : i8, 109 : i8, 101 : i8, 34 : i8, 58 : i8, 34 : i8, 83 : i8, 101 : i8, 108 : i8, 102 : i8, 65 : i8, 116 : i8, 116 : i8, 101 : i8, 110 : i8, 116 : i8, 105 : i8, 111 : i8, 110 : i8, 79 : i8, 112 : i8, 34 : i8, 125 : i8] : !spirv.array<35 x i8>
+    %attrs = spirv.Constant dense<[123, 34, 111, 112, 101, 114, 97, 116, 111, 114, 95, 110, 97, 109, 101, 34, 58, 34, 83, 101, 108, 102, 65, 116, 116, 101, 110, 116, 105, 111, 110, 79, 112, 34, 125]> : tensor<35xi8> : !spirv.array<35 x i8>
+    // CHECK: %[[CALL:.*]] = spirv.ExperimentalML.Call opcode = 0, %[[NAME]], %[[ATTRS]], %arg0, %arg1 : (!spirv.array<15 x i8>, !spirv.array<35 x i8>, !spirv.arm.tensor<1x16xf32>, !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32>
+    %0 = spirv.ExperimentalML.Call opcode = 0, %name, %attrs, %arg0, %arg1 : (!spirv.array<15 x i8>, !spirv.array<35 x i8>, !spirv.arm.tensor<1x16xf32>, !spirv.arm.tensor<1x16xf32>) -> !spirv.arm.tensor<1x16xf32>
+    // CHECK: spirv.ARM.GraphOutputs %[[CALL]] : !spirv.arm.tensor<1x16xf32>
+    spirv.ARM.GraphOutputs %0 : !spirv.arm.tensor<1x16xf32>
+  }
+}


        


More information about the Mlir-commits mailing list