[Mlir-commits] [mlir] [MLIR][spirv] Shard generated operation definitions (NFC) (PR #221811)
Mehdi Amini
llvmlistbot at llvm.org
Mon Sep 7 12:47:58 PDT 2026
https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/221811
Generate SPIR-V operation definitions in eight shards and use the generated registration hook. Keep parser, printer, and verification helpers in the existing implementation TU and expose them through a private header.
Assisted-by: Codex
>From eff68d7d3a266ea5d4ccc0bbfd0eb534107287bc Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Mon, 7 Sep 2026 06:16:27 -0700
Subject: [PATCH] [mlir][spirv] Shard generated operation definitions
Generate SPIR-V operation definitions in eight shards and use the generated
registration hook. Keep parser, printer, and verification helpers in the
existing implementation TU and expose them through a private header.
The baseline had two generated-code hotspots. SPIRVOpDefinition.cpp took an
87.714s Ninja edge and 87.302s ExecuteCompiler, including 25.794s frontend and
61.232s backend. SPIRVDialect.cpp took an 84.334s Ninja edge and 83.921s
ExecuteCompiler, including 38.294s frontend and 44.996s backend.
Together the baseline TUs totaled 171.223s ExecuteCompiler, 64.088s frontend,
106.227s backend, 61.542s optimizer, 44.534s code generation, 30.043s function
instantiation, 16.321s class instantiation, 27.690s source processing, and
11.651s class parsing.
The eight shards plus the remaining dialect and helper TUs totaled 129.831s
ExecuteCompiler, 75.478s frontend, 53.463s backend, 32.319s optimizer, 21.070s
code generation, 21.471s function instantiation, 22.085s class instantiation,
52.613s source processing, and 36.961s class parsing. The slowest new compile
edge was 15.987s.
Aggregate compiler time fell 24.2%, backend time fell 49.7%, optimizer time
fell 47.5%, code-generation time fell 52.7%, and function-instantiation time
fell 28.5%. The longest compile edge fell 81.8%. Repeated work increased
frontend time 17.8%, class-instantiation time 35.3%, source-processing time
90.0%, and class-parsing time 217.2%.
The affected-target build ran 36 steps in 25.72s wall time, including 3.5s of
CMake configuration and 4.2s of generation. It used 212.12s user time and
12.47s system time at 873% CPU, with 945,124 KiB peak RSS and zero swaps. The
public generated-header change also rebuilt 18 otherwise unchanged SPIR-V
implementation TUs, so this wall time is not limited to the ten measured TUs.
The two baseline objects contained 9,312,757 text bytes; the remaining dialect
and helper objects plus eight shard objects contain 10,062,118 text bytes, an
increase of 8.0%. The static archive grew from 47,932,124 to 49,655,616 bytes,
an increase of 3.6%.
Rebuilding mlir-opt and running six focused suites took 30.57s wall time,
572.23s user time, and 47.65s system time at 2,027% CPU, with 1,634,280 KiB
peak RSS and zero swaps. The suites ran 15 tests in 0.14s, 23 in 0.16s, 52 in
0.28s, 36 in 0.25s, 12 in 0.17s, and 59 in 0.26s; all 197 tests passed.
The full check-mlir invocation took 6.34s wall time, 1.52s user time, and
0.35s system time at 29% CPU, with 175,504 KiB peak RSS and zero swaps. Its
lit suite ran in 5.52s with 3,937 passed, 619 unsupported, and 1 expected
failure.
Assisted-by: Codex
---
.../mlir/Dialect/SPIRV/IR/CMakeLists.txt | 9 +++-
mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h | 1 +
mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt | 15 +++++++
mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp | 6 +--
.../Dialect/SPIRV/IR/SPIRVOpDefinition.cpp | 40 ++++++++---------
mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.h | 43 +++++++++++++++++++
.../Dialect/SPIRV/IR/SPIRVOpDefinitions.cpp | 17 ++++++++
7 files changed, 103 insertions(+), 28 deletions(-)
create mode 100644 mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.h
create mode 100644 mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinitions.cpp
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/CMakeLists.txt b/mlir/include/mlir/Dialect/SPIRV/IR/CMakeLists.txt
index 821211dcd0891..d50e5d5ef787c 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/CMakeLists.txt
@@ -1,4 +1,11 @@
-add_mlir_dialect(SPIRVOps spirv)
+set(LLVM_TARGET_DEFINITIONS SPIRVOps.td)
+mlir_tablegen(SPIRVOps.h.inc -gen-op-decls -op-shard-count=8)
+mlir_tablegen(SPIRVOps.cpp.inc -gen-op-defs -op-shard-count=8)
+mlir_tablegen(SPIRVOpsTypes.h.inc -gen-typedef-decls -typedefs-dialect=spirv)
+mlir_tablegen(SPIRVOpsTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=spirv)
+mlir_tablegen(SPIRVOpsDialect.h.inc -gen-dialect-decls -dialect=spirv)
+mlir_tablegen(SPIRVOpsDialect.cpp.inc -gen-dialect-defs -dialect=spirv)
+add_mlir_dialect_tablegen_target(MLIRSPIRVOpsIncGen)
add_mlir_doc(SPIRVOps SPIRVOps Dialects/ -gen-op-doc -dialect=spirv)
set(LLVM_TARGET_DEFINITIONS SPIRVBase.td)
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
index 34e2ff388bcea..2c914d566a747 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVOps.h
@@ -38,6 +38,7 @@ class OpBuilder;
namespace spirv {
class VerCapExtAttr;
+class SPIRVDialect;
} // namespace spirv
} // namespace mlir
diff --git a/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt b/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
index f05f596aa9f23..742272163cd82 100644
--- a/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/SPIRV/IR/CMakeLists.txt
@@ -2,6 +2,19 @@ set(LLVM_TARGET_DEFINITIONS SPIRVCanonicalization.td)
mlir_tablegen(SPIRVCanonicalization.inc -gen-rewriters)
add_public_tablegen_target(MLIRSPIRVCanonicalizationIncGen)
+set(LLVM_OPTIONAL_SOURCES
+ SPIRVOpDefinitions.cpp
+ )
+
+set(LLVM_TARGET_DEFINITIONS SPIRVOpDefinitions.cpp)
+foreach(index RANGE 7)
+ set(SPIRV_SHARDED_SRC SPIRVOpDefinitions.${index}.cpp)
+ list(APPEND SPIRV_SHARDED_SRCS ${SPIRV_SHARDED_SRC})
+ tablegen(MLIR_SRC_SHARDER ${SPIRV_SHARDED_SRC}
+ -op-shard-index=${index})
+endforeach()
+add_public_tablegen_target(MLIRSPIRVOpsShardGen)
+
add_mlir_dialect_library(MLIRSPIRVDialect
ArmGraphOps.cpp
AtomicOps.cpp
@@ -25,6 +38,7 @@ add_mlir_dialect_library(MLIRSPIRVDialect
SPIRVTosaOps.cpp
SPIRVTypes.cpp
TargetAndABI.cpp
+ ${SPIRV_SHARDED_SRCS}
ADDITIONAL_HEADER_DIRS
${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/SPIRV
@@ -39,6 +53,7 @@ add_mlir_dialect_library(MLIRSPIRVDialect
MLIRSPIRVEnumsIncGen
MLIRSPIRVImageInterfacesIncGen
MLIRSPIRVOpsIncGen
+ MLIRSPIRVOpsShardGen
LINK_LIBS PUBLIC
MLIRControlFlowInterfaces
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp
index 0e851fe68389c..2ab675221bd11 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVDialect.cpp
@@ -127,11 +127,7 @@ void SPIRVDialect::initialize() {
registerAttributes();
registerTypes();
- // Add SPIR-V ops.
- addOperations<
-#define GET_OP_LIST
-#include "mlir/Dialect/SPIRV/IR/SPIRVOps.cpp.inc"
- >();
+ registerSPIRVDialectOperations(this);
addInterfaces<SPIRVInlinerInterface>();
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.cpp
index b9075da95a617..4773ff6cb2181 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.cpp
@@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
//
-// Defines the TableGen'erated SPIR-V op implementation in the SPIR-V dialect.
-// These are placed in a separate file to reduce the total amount of code in
-// SPIRVOps.cpp and make that file faster to recompile.
+// Defines helpers referenced by the TableGen-generated SPIR-V operation
+// implementations.
//
//===----------------------------------------------------------------------===//
#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
+#include "SPIRVOpDefinition.h"
#include "SPIRVParsingUtils.h"
#include "mlir/IR/TypeUtilities.h"
@@ -21,7 +21,7 @@
namespace mlir::spirv {
/// Returns true if the given op is a function-like op or nested in a
/// function-like op without a module-like op in the middle.
-static bool isNestedInFunctionOpInterface(Operation *op) {
+bool isNestedInFunctionOpInterface(Operation *op) {
if (!op)
return false;
if (op->hasTrait<OpTrait::SymbolTable>())
@@ -33,7 +33,7 @@ static bool isNestedInFunctionOpInterface(Operation *op) {
/// Returns true if the given op is a GraphARM op or nested in a
/// GraphARM op without a module-like op in the middle.
-static bool isNestedInGraphARMOpInterface(Operation *op) {
+bool isNestedInGraphARMOpInterface(Operation *op) {
if (!op)
return false;
if (op->hasTrait<OpTrait::SymbolTable>())
@@ -45,13 +45,13 @@ static bool isNestedInGraphARMOpInterface(Operation *op) {
/// Returns true if the given op is an module-like op that maintains a symbol
/// table.
-static bool isDirectInModuleLikeOp(Operation *op) {
+bool isDirectInModuleLikeOp(Operation *op) {
return op && op->hasTrait<OpTrait::SymbolTable>();
}
/// Returns a boolean scalar or vector type matching the shape of the given
/// type. Scalar inputs yield i1, vector inputs yield vector<Nxi1>.
-static Type getMatchingBoolType(Type operandType) {
+Type getMatchingBoolType(Type operandType) {
Builder builder(operandType.getContext());
Type resultType = builder.getIntegerType(1);
if (auto vecType = dyn_cast<VectorType>(operandType))
@@ -59,8 +59,8 @@ static Type getMatchingBoolType(Type operandType) {
return resultType;
}
-static ParseResult parseImageOperands(OpAsmParser &parser,
- spirv::ImageOperandsAttr &attr) {
+ParseResult parseImageOperands(OpAsmParser &parser,
+ spirv::ImageOperandsAttr &attr) {
// Expect image operands
if (parser.parseOptionalLSquare())
return success();
@@ -74,8 +74,8 @@ static ParseResult parseImageOperands(OpAsmParser &parser,
return parser.parseRSquare();
}
-static void printImageOperands(OpAsmPrinter &printer, Operation *imageOp,
- spirv::ImageOperandsAttr attr) {
+void printImageOperands(OpAsmPrinter &printer, Operation *imageOp,
+ spirv::ImageOperandsAttr attr) {
if (attr) {
auto strImageOperands = stringifyImageOperands(attr.getValue());
printer << "[\"" << strImageOperands << "\"]";
@@ -85,7 +85,7 @@ static void printImageOperands(OpAsmPrinter &printer, Operation *imageOp,
/// Adapted from the cf.switch implementation.
/// <cases> ::= `default` `:` bb-id (`(` ssa-use-and-type-list `)`)?
/// ( `,` integer `:` bb-id (`(` ssa-use-and-type-list `)`)? )*
-static ParseResult parseSwitchOpCases(
+ParseResult parseSwitchOpCases(
OpAsmParser &parser, Type &selectorType, Block *&defaultTarget,
SmallVectorImpl<OpAsmParser::UnresolvedOperand> &defaultOperands,
SmallVectorImpl<Type> &defaultOperandTypes, DenseIntElementsAttr &literals,
@@ -136,12 +136,12 @@ static ParseResult parseSwitchOpCases(
return success();
}
-static void
-printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type selectorType,
- Block *defaultTarget, OperandRange defaultOperands,
- TypeRange defaultOperandTypes, DenseIntElementsAttr literals,
- SuccessorRange targets, OperandRangeRange targetOperands,
- const TypeRangeRange &targetOperandTypes) {
+void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type selectorType,
+ Block *defaultTarget, OperandRange defaultOperands,
+ TypeRange defaultOperandTypes,
+ DenseIntElementsAttr literals, SuccessorRange targets,
+ OperandRangeRange targetOperands,
+ const TypeRangeRange &targetOperandTypes) {
p << " default: ";
p.printSuccessorAndUseList(defaultTarget, defaultOperands);
@@ -160,7 +160,3 @@ printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type selectorType,
}
} // namespace mlir::spirv
-
-// TablenGen'erated operation definitions.
-#define GET_OP_CLASSES
-#include "mlir/Dialect/SPIRV/IR/SPIRVOps.cpp.inc"
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.h b/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.h
new file mode 100644
index 0000000000000..305757b64a60f
--- /dev/null
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinition.h
@@ -0,0 +1,43 @@
+//===- SPIRVOpDefinition.h - SPIR-V op implementation helpers --*- C++ -*-===//
+//
+// 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_LIB_DIALECT_SPIRV_IR_SPIRVOPDEFINITION_H
+#define MLIR_LIB_DIALECT_SPIRV_IR_SPIRVOPDEFINITION_H
+
+#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
+
+namespace mlir::spirv {
+
+bool isNestedInFunctionOpInterface(Operation *op);
+bool isNestedInGraphARMOpInterface(Operation *op);
+bool isDirectInModuleLikeOp(Operation *op);
+Type getMatchingBoolType(Type operandType);
+
+ParseResult parseImageOperands(OpAsmParser &parser,
+ spirv::ImageOperandsAttr &attr);
+void printImageOperands(OpAsmPrinter &printer, Operation *imageOp,
+ spirv::ImageOperandsAttr attr);
+
+ParseResult parseSwitchOpCases(
+ OpAsmParser &parser, Type &selectorType, Block *&defaultTarget,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &defaultOperands,
+ SmallVectorImpl<Type> &defaultOperandTypes, DenseIntElementsAttr &literals,
+ SmallVectorImpl<Block *> &targets,
+ SmallVectorImpl<SmallVector<OpAsmParser::UnresolvedOperand>>
+ &targetOperands,
+ SmallVectorImpl<SmallVector<Type>> &targetOperandTypes);
+void printSwitchOpCases(OpAsmPrinter &p, SwitchOp op, Type selectorType,
+ Block *defaultTarget, OperandRange defaultOperands,
+ TypeRange defaultOperandTypes,
+ DenseIntElementsAttr literals, SuccessorRange targets,
+ OperandRangeRange targetOperands,
+ const TypeRangeRange &targetOperandTypes);
+
+} // namespace mlir::spirv
+
+#endif // MLIR_LIB_DIALECT_SPIRV_IR_SPIRVOPDEFINITION_H
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinitions.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinitions.cpp
new file mode 100644
index 0000000000000..c41cf1c142cc4
--- /dev/null
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOpDefinitions.cpp
@@ -0,0 +1,17 @@
+//===- SPIRVOpDefinitions.cpp - Generated SPIR-V op definitions ----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h"
+#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
+
+#include "SPIRVOpDefinition.h"
+
+using namespace mlir;
+using namespace mlir::spirv;
+
+#include "mlir/Dialect/SPIRV/IR/SPIRVOps.cpp.inc"
More information about the Mlir-commits
mailing list