[mlir] Fix assertion crash in test-symbol-uses with nested modules (#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
This commit is contained in:
Mehdi Amini 2026-03-06 19:05:06 +01:00 committed by GitHub
parent cba914cece
commit 1a23e643be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 18 additions and 1 deletions

View file

@ -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@below {{symbol has no uses}}
func.func private @printMemrefF32(%ptr : memref<*xf32>)
}
}

View file

@ -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";