[Mlir-commits] [mlir] [mlir] Fix assertion crash in test-symbol-uses with nested modules (PR #185069)
Mehdi Amini
llvmlistbot at llvm.org
Fri Mar 6 09:57:11 PST 2026
https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/185069
The `SymbolUsesPass` walked all nested `SymbolOpInterface` ops in a module, including those belonging to nested symbol tables (e.g., nested modules). When an external `func.func` inside a nested module had no uses in the outer module's body region, it was incorrectly added to `deadFunctions` for erasure. Since the outer module's `SymbolTable` does not contain the inner module's symbols, the subsequent `table.lookup(name)` assertion would fail with:
Assertion `table.lookup(name) && "expected no unknown operations"` failed.
Fix by only tracking functions that are direct children of the enclosing module, skipping functions owned by nested symbol tables.
Fixes #60583
Assisted-by: Claude Code
>From 2bd18036e622a18df9a5beafd8949eff4b0b53cd Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 5 Mar 2026 08:23:52 -0800
Subject: [PATCH] [mlir] Fix assertion crash in test-symbol-uses with nested
modules
The `SymbolUsesPass` walked all nested `SymbolOpInterface` ops in a
module, including those belonging to nested symbol tables (e.g., nested
modules). When an external `func.func` inside a nested module had no
uses in the outer module's body region, it was incorrectly added to
`deadFunctions` for erasure. Since the outer module's `SymbolTable`
does not contain the inner module's symbols, the subsequent
`table.lookup(name)` assertion would fail with:
Assertion `table.lookup(name) && "expected no unknown operations"` failed.
Fix by only tracking functions that are direct children of the enclosing
module, skipping functions owned by nested symbol tables.
Fixes #60583
Assisted-by: Claude Code
---
mlir/test/IR/test-symbol-uses.mlir | 12 ++++++++++++
mlir/test/lib/IR/TestSymbolUses.cpp | 7 ++++++-
2 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/mlir/test/IR/test-symbol-uses.mlir b/mlir/test/IR/test-symbol-uses.mlir
index d9d839e9fc307..eb0c5c379bb31 100644
--- a/mlir/test/IR/test-symbol-uses.mlir
+++ b/mlir/test/IR/test-symbol-uses.mlir
@@ -93,3 +93,15 @@ module {
return
}
}
+
+// -----
+
+// Test that external functions in nested modules are not incorrectly erased
+// from the outer module's symbol table.
+// Regression test for https://github.com/llvm/llvm-project/issues/60583
+module {
+ module {
+ // expected-remark at below {{symbol has no uses}}
+ func.func private @printMemrefF32(%ptr : memref<*xf32>)
+ }
+}
diff --git a/mlir/test/lib/IR/TestSymbolUses.cpp b/mlir/test/lib/IR/TestSymbolUses.cpp
index 24f7d8505bebd..6aac9bfc8baa4 100644
--- a/mlir/test/lib/IR/TestSymbolUses.cpp
+++ b/mlir/test/lib/IR/TestSymbolUses.cpp
@@ -43,7 +43,12 @@ struct SymbolUsesPass
// Test the functionality of symbolKnownUseEmpty.
if (SymbolTable::symbolKnownUseEmpty(symbol, &module.getBodyRegion())) {
func::FuncOp funcSymbol = dyn_cast<func::FuncOp>(symbol.getOperation());
- if (funcSymbol && funcSymbol.isExternal())
+ // Only track functions that are direct children of the enclosing module.
+ // Functions in nested symbol tables (e.g., nested modules) belong to a
+ // different symbol table and cannot be erased via the outer module's
+ // SymbolTable instance.
+ if (funcSymbol && funcSymbol.isExternal() &&
+ funcSymbol->getParentOp() == module.getOperation())
deadFunctions.push_back(funcSymbol);
symbol->emitRemark() << "symbol has no uses";
More information about the Mlir-commits
mailing list