[Mlir-commits] [mlir] [MLIR] Fix allSymUsesVisible inside private symbol table (PR #179596)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Feb 3 21:15:42 PST 2026


https://github.com/neildhar updated https://github.com/llvm/llvm-project/pull/179596

>From efba25535ab0ee848120d3de715fcf1fca88ab75 Mon Sep 17 00:00:00 2001
From: Neil Dhar <neildhar at meta.com>
Date: Tue, 3 Feb 2026 18:37:05 -0800
Subject: [PATCH] [MLIR] Fix allSymUsesVisible inside private symbol table

We currently always set `allSymUsesVisible` to true if the current
operation is a symbol table that defines a private symbol. However, this
is incorrect since the symbols inside that symbol table can still be
referenced by siblings of the symbol table.

For example, if we have a nested module defining a private symbol, the
functions inside it may be referenced by functions in the outer module.

This can affect `DeadCodeAnalysis` for example, which computes whether a
callable's uses are all known.
---
 mlir/lib/IR/SymbolTable.cpp                      |  6 ++++--
 .../test-dead-code-analysis-nested-module.mlir   | 16 ++++++++++++++++
 2 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 mlir/test/Analysis/DataFlow/test-dead-code-analysis-nested-module.mlir

diff --git a/mlir/lib/IR/SymbolTable.cpp b/mlir/lib/IR/SymbolTable.cpp
index 4e191e7d612ad..5c2a23198d357 100644
--- a/mlir/lib/IR/SymbolTable.cpp
+++ b/mlir/lib/IR/SymbolTable.cpp
@@ -358,8 +358,10 @@ void SymbolTable::walkSymbolTables(
     function_ref<void(Operation *, bool)> callback) {
   bool isSymbolTable = op->hasTrait<OpTrait::SymbolTable>();
   if (isSymbolTable) {
-    SymbolOpInterface symbol = dyn_cast<SymbolOpInterface>(op);
-    allSymUsesVisible |= !symbol || symbol.isPrivate();
+    // If the symbol table does not define a symbol, any operations outside the
+    // symbol table cannot reference the symbols inside it, so all their uses
+    // are visible.
+    allSymUsesVisible |= !isa<SymbolOpInterface>(op);
   } else {
     // Otherwise if 'op' is not a symbol table, any nested symbols are
     // guaranteed to be hidden.
diff --git a/mlir/test/Analysis/DataFlow/test-dead-code-analysis-nested-module.mlir b/mlir/test/Analysis/DataFlow/test-dead-code-analysis-nested-module.mlir
new file mode 100644
index 0000000000000..0d10d011d79b4
--- /dev/null
+++ b/mlir/test/Analysis/DataFlow/test-dead-code-analysis-nested-module.mlir
@@ -0,0 +1,16 @@
+// RUN: mlir-opt --pass-pipeline="builtin.module(builtin.module(test-dead-code-analysis))" %s 2>&1 | FileCheck %s
+
+// Test that when dead code analysis runs directly on a nested module with a
+// private symbol name, we account for the fact that functions within that
+// module may be invoked from outside the module.
+module {
+  module @inner_module attributes {sym_visibility = "private"} {
+    // CHECK:      nested:
+    // CHECK-NEXT:  region #0
+    // CHECK-NEXT:   ^bb0 = live
+    // CHECK-NEXT: op_preds: predecessors: (none)
+    func.func nested @nested_inner(%arg0: i32) -> i32 attributes {tag = "nested"} {
+      return %arg0 : i32
+    }
+  }
+}



More information about the Mlir-commits mailing list