[Mlir-commits] [mlir] [mlir][SPIR-V] Move symbol lookups into verifySymbolUses (PR #235042)
Arseniy Obolenskiy
llvmlistbot at llvm.org
Fri Oct 23 10:57:18 PDT 2026
https://github.com/aobolensk created https://github.com/llvm/llvm-project/pull/235042
Looking up symbols in verify() made verification quadratic
>From 1892b106493c8f32dff04df2c8b702b0be3d1887 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 23 Oct 2026 19:45:54 +0200
Subject: [PATCH] [mlir][SPIR-V] Move symbol lookups into verifySymbolUses
Looking up symbols in verify() made verification quadratic
---
.../Dialect/SPIRV/IR/SPIRVStructureOps.td | 23 ++++--
mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp | 72 +++++++++++--------
mlir/test/Dialect/SPIRV/IR/structure-ops.mlir | 2 +
3 files changed, 62 insertions(+), 35 deletions(-)
diff --git a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
index c8cd881f138c58..e1959dbf8767e5 100644
--- a/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
+++ b/mlir/include/mlir/Dialect/SPIRV/IR/SPIRVStructureOps.td
@@ -28,6 +28,7 @@ include "mlir/Interfaces/SideEffectInterfaces.td"
def SPIRV_AddressOfOp : SPIRV_Op<"mlir.addressof",
[DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>,
InFunctionScope, Pure]> {
let summary = "Get the address of a global variable.";
@@ -62,6 +63,8 @@ def SPIRV_AddressOfOp : SPIRV_Op<"mlir.addressof",
let builders = [OpBuilder<(ins "spirv::GlobalVariableOp":$var)>];
let assemblyFormat = "$variable attr-dict `:` type($pointer)";
+
+ let hasVerifier = 0;
}
// -----
@@ -290,7 +293,8 @@ def SPIRV_ExecutionModeOp : SPIRV_Op<"ExecutionMode", [InModuleScope]> {
// -----
-def SPIRV_ExecutionModeIdOp : SPIRV_Op<"ExecutionModeId", []> {
+def SPIRV_ExecutionModeIdOp : SPIRV_Op<"ExecutionModeId", [
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = [{
Declare an execution mode for an entry point, using <id>s as Extra
Operands.
@@ -465,9 +469,9 @@ def SPIRV_FuncOp : SPIRV_Op<"func", [
// -----
-def SPIRV_GlobalVariableOp
- : SPIRV_Op<"GlobalVariable", [InModuleScope, SymbolName, SymbolVisibility,
- Symbol]> {
+def SPIRV_GlobalVariableOp : SPIRV_Op<"GlobalVariable", [
+ InModuleScope, SymbolName, SymbolVisibility, Symbol,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = [{
Allocate an object in memory at module scope. The object is
referenced using a symbol name.
@@ -659,7 +663,8 @@ def SPIRV_ModuleOp : SPIRV_Op<"module",
// -----
-def SPIRV_ReferenceOfOp : SPIRV_Op<"mlir.referenceof", [Pure]> {
+def SPIRV_ReferenceOfOp : SPIRV_Op<"mlir.referenceof", [
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>, Pure]> {
let summary = "Reference a specialization constant.";
let description = [{
@@ -692,6 +697,8 @@ def SPIRV_ReferenceOfOp : SPIRV_Op<"mlir.referenceof", [Pure]> {
let autogenSerialization = 0;
let assemblyFormat = "$spec_const attr-dict `:` type($reference)";
+
+ let hasVerifier = 0;
}
// -----
@@ -750,7 +757,8 @@ def SPIRV_SpecConstantOp
// -----
def SPIRV_SpecConstantCompositeOp : SPIRV_Op<"SpecConstantComposite", [
- InModuleScope, SymbolName, SymbolVisibility, Symbol]> {
+ InModuleScope, SymbolName, SymbolVisibility, Symbol,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = "Declare a new composite specialization constant.";
let description = [{
@@ -806,7 +814,8 @@ def SPIRV_SpecConstantCompositeOp : SPIRV_Op<"SpecConstantComposite", [
def SPIRV_EXTSpecConstantCompositeReplicateOp
: SPIRV_ExtVendorOp<"SpecConstantCompositeReplicate",
- [InModuleScope, SymbolName, SymbolVisibility, Symbol]> {
+ [InModuleScope, SymbolName, SymbolVisibility, Symbol,
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>]> {
let summary = "Declare a new replicated composite specialization constant op.";
let description = [{
diff --git a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
index 35cb37a67f530a..47deba50ffbdbc 100644
--- a/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
+++ b/mlir/lib/Dialect/SPIRV/IR/SPIRVOps.cpp
@@ -358,10 +358,10 @@ void spirv::AddressOfOp::build(OpBuilder &builder, OperationState &state,
build(builder, state, var.getType(), SymbolRefAttr::get(var));
}
-LogicalResult spirv::AddressOfOp::verify() {
- auto varOp = dyn_cast_or_null<spirv::GlobalVariableOp>(
- SymbolTable::lookupNearestSymbolFrom((*this)->getParentOp(),
- getVariableAttr()));
+LogicalResult
+spirv::AddressOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
+ auto varOp = symbolTable.lookupNearestSymbolFrom<spirv::GlobalVariableOp>(
+ *this, getVariableAttr());
if (!varOp) {
return emitOpError("expected spirv.GlobalVariable symbol");
}
@@ -1105,17 +1105,19 @@ LogicalResult spirv::ExecutionModeIdOp::verify() {
<< schema.numOperands << " value operand(s), got "
<< getValues().size();
- for (Attribute value : getValues()) {
- auto valueSymbol = dyn_cast<FlatSymbolRefAttr>(value);
- if (!valueSymbol)
- return emitOpError("expected value operands to be symbol reference");
- Operation *valueOp = SymbolTable::lookupNearestSymbolFrom(
- (*this)->getParentOp(), valueSymbol);
- if (!valueOp)
+ if (!llvm::all_of(getValues(), llvm::IsaPred<FlatSymbolRefAttr>))
+ return emitOpError("expected value operands to be symbol reference");
+
+ return success();
+}
+
+LogicalResult
+spirv::ExecutionModeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
+ for (auto valueSymbol : getValues().getAsRange<FlatSymbolRefAttr>()) {
+ if (!symbolTable.lookupNearestSymbolFrom(*this, valueSymbol))
return emitOpError("cannot find symbol referenced by value operand: ")
<< valueSymbol.getValue();
}
-
return success();
}
@@ -1511,9 +1513,14 @@ LogicalResult spirv::GlobalVariableOp::verify() {
}
}
+ Type pointeeType = cast<spirv::PointerType>(getType()).getPointeeType();
+ return verifyPhysicalStorageBufferDecorations(getOperation(), pointeeType);
+}
+
+LogicalResult
+spirv::GlobalVariableOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
if (FlatSymbolRefAttr init = getInitializerAttr()) {
- Operation *initOp = SymbolTable::lookupNearestSymbolFrom(
- (*this)->getParentOp(), init.getAttr());
+ Operation *initOp = symbolTable.lookupNearestSymbolFrom(*this, init);
// TODO: Currently only variable initialization with specialization
// constants is supported. There could be normal constants in the module
// scope as well.
@@ -1532,11 +1539,6 @@ LogicalResult spirv::GlobalVariableOp::verify() {
}
}
- Type pointeeType = cast<spirv::PointerType>(getType()).getPointeeType();
- if (failed(
- verifyPhysicalStorageBufferDecorations(getOperation(), pointeeType)))
- return failure();
-
return success();
}
@@ -1847,9 +1849,10 @@ LogicalResult spirv::ModuleOp::verifyRegions() {
// spirv.mlir.referenceof
//===----------------------------------------------------------------------===//
-LogicalResult spirv::ReferenceOfOp::verify() {
- auto *specConstSym = SymbolTable::lookupNearestSymbolFrom(
- (*this)->getParentOp(), getSpecConstAttr());
+LogicalResult
+spirv::ReferenceOfOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
+ auto *specConstSym =
+ symbolTable.lookupNearestSymbolFrom(*this, getSpecConstAttr());
Type constType;
auto specConstOp = dyn_cast_or_null<spirv::SpecConstantOp>(specConstSym);
@@ -2036,11 +2039,19 @@ LogicalResult spirv::SpecConstantCompositeOp::verify() {
<< cType.getNumElements() << ", but provided "
<< constituents.size();
+ return success();
+}
+
+LogicalResult spirv::SpecConstantCompositeOp::verifySymbolUses(
+ SymbolTableCollection &symbolTable) {
+ auto cType = cast<spirv::CompositeType>(getType());
+ auto constituents = this->getConstituents().getValue();
+
for (auto index : llvm::seq<uint32_t>(0, constituents.size())) {
auto constituent = cast<FlatSymbolRefAttr>(constituents[index]);
- Operation *constituentOp = SymbolTable::lookupNearestSymbolFrom(
- (*this)->getParentOp(), constituent.getAttr());
+ Operation *constituentOp =
+ symbolTable.lookupNearestSymbolFrom(*this, constituent);
if (!constituentOp)
return emitError("unknown constituent symbol ") << constituent.getAttr();
@@ -2110,13 +2121,18 @@ void spirv::EXTSpecConstantCompositeReplicateOp::print(OpAsmPrinter &printer) {
}
LogicalResult spirv::EXTSpecConstantCompositeReplicateOp::verify() {
- auto compositeType = dyn_cast<spirv::CompositeType>(getType());
- if (!compositeType)
+ if (!isa<spirv::CompositeType>(getType()))
return emitError("result type must be a composite type, but provided ")
<< getType();
- Operation *constituentOp = SymbolTable::lookupNearestSymbolFrom(
- (*this)->getParentOp(), this->getConstituent());
+ return success();
+}
+
+LogicalResult spirv::EXTSpecConstantCompositeReplicateOp::verifySymbolUses(
+ SymbolTableCollection &symbolTable) {
+ auto compositeType = cast<spirv::CompositeType>(getType());
+ Operation *constituentOp =
+ symbolTable.lookupNearestSymbolFrom(*this, getConstituent());
if (!constituentOp)
return emitError(
"splat spec constant reference defining constituent not found");
diff --git a/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir b/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
index 4acaa417501ac5..996755ab7783e3 100644
--- a/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
+++ b/mlir/test/Dialect/SPIRV/IR/structure-ops.mlir
@@ -33,6 +33,7 @@ spirv.module Logical GLSL450 {
spirv.func @foo() -> () "None" {
// expected-error @+1 {{expected spirv.GlobalVariable symbol}}
%0 = spirv.mlir.addressof @var2 : !spirv.ptr<!spirv.struct<(f32, !spirv.array<4xf32>)>, Input>
+ spirv.Return
}
}
@@ -43,6 +44,7 @@ spirv.module Logical GLSL450 {
spirv.func @foo() -> () "None" {
// expected-error @+1 {{result type mismatch with the referenced global variable's type}}
%0 = spirv.mlir.addressof @var1 : !spirv.ptr<f32, Input>
+ spirv.Return
}
}
More information about the Mlir-commits
mailing list