llvm / llvm/llvm-project

[mlir][Inliner] Assertion \symbolUses && "expected uses to be valid" on function with no terminator containing an op with a region

Open
#197,960 4 comments 0 reactions 0 assignees View on GitHub
crash generated by fuzzer mlir
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Summary

The MLIR inliner crashes with an assertion failure when processing a `func.func` that has no return terminator and contains an unregistered op with a region. The assertion fires in `walkReferencedSymbolNodes` during call graph construction.

## Assertion

```
mlir-opt: mlir/lib/Transforms/Utils/Inliner.cpp:42:
void walkReferencedSymbolNodes(...):
Assertion `symbolUses && "expected uses to be valid"' failed.
```

## Minimal Reproducer

**File (`min.mlir`):**
```mlir
module {
func.func @f() {
"a.b"() ({}) : () -> ()
}
}
```

**Command:**
```
mlir-opt --allow-unregistered-dialect --inline min.mlir
```

## Stack Trace (key frames)

```
#9 walkReferencedSymbolNodes(...) Inliner.cpp:62
#12 CGUseList::recomputeUses(...) Inliner.cpp:233
#13 CGUseList(...) Inliner.cpp:159
#14 mlir::Inliner::doInlining() Inliner.cpp:759
#15 InlinerPass::runOnOperation() InlinerPass.cpp:152
```

## Analysis

The inliner calls `SymbolTable::getSymbolUses()` on the parent region of an operation during call graph construction. When a `func.func` has no terminator (not caught by a verifier pass beforehand because `--allow-unregistered-dialect` relaxes verification), the function body is malformed in a way that causes `getSymbolUses()` to return `std::nullopt` — indicating the symbol table is not analyzable for that scope. The assertion on the returned value then fires unconditionally rather than handling the failure gracefully.

The inliner should either (a) guard against `std::nullopt` from `getSymbolUses()` and emit a diagnostic instead of asserting, or (b) run the verifier before the inliner to reject malformed inputs early.

## Environment

- MLIR from `llvm-project` (see build at `projects/mlir/llvm-mlir-build`)
- Triggered with `--allow-unregistered-dialect --inline`
- Also triggered with the full pass pipeline: `--allow-unregistered-dialect --inline --loop-invariant-code-motion --cse --canonicalize --symbol-dce --sccp --verify-each`

*This bug was found by [fusion-fuzz](https://github.com/fusion-fuzz/fusion-fuzz)*

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.