[Mlir-commits] [mlir] [mlir][transforms] Fix crash in remove-dead-values when function has non-call users (PR #183655)

Mehdi Amini llvmlistbot at llvm.org
Thu Feb 26 16:59:35 PST 2026


https://github.com/joker-eph created https://github.com/llvm/llvm-project/pull/183655

`processFuncOp` asserts that all symbol uses of a function are `CallOpInterface` operations. This is violated when a function is referenced by a non-call operation such as `spirv.EntryPoint`, which uses the function symbol for metadata purposes without calling it.

Fix this by replacing the assertion with an early return: if any user of the function symbol is not a `CallOpInterface`, skip the function entirely. This is safe because the pass cannot determine the semantics of arbitrary non-call references, so it should leave such functions alone.

Fixes #180416

>From 09f1a85f8253b82b65df0045b6c101564003d72d Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Thu, 26 Feb 2026 16:56:33 -0800
Subject: [PATCH] [mlir][transforms] Fix crash in remove-dead-values when
 function has non-call users

`processFuncOp` asserts that all symbol uses of a function are
`CallOpInterface` operations. This is violated when a function is
referenced by a non-call operation such as `spirv.EntryPoint`, which
uses the function symbol for metadata purposes without calling it.

Fix this by replacing the assertion with an early return: if any user of
the function symbol is not a `CallOpInterface`, skip the function
entirely. This is safe because the pass cannot determine the semantics of
arbitrary non-call references, so it should leave such functions alone.

Fixes #180416
---
 mlir/lib/Transforms/RemoveDeadValues.cpp     |  6 +++++-
 mlir/test/Transforms/remove-dead-values.mlir | 13 +++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Transforms/RemoveDeadValues.cpp b/mlir/lib/Transforms/RemoveDeadValues.cpp
index 12a47ba2fb65a..c70cd8d6beb68 100644
--- a/mlir/lib/Transforms/RemoveDeadValues.cpp
+++ b/mlir/lib/Transforms/RemoveDeadValues.cpp
@@ -302,7 +302,11 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module,
   SymbolTable::UseRange uses = *funcOp.getSymbolUses(module);
   for (SymbolTable::SymbolUse use : uses) {
     Operation *callOp = use.getUser();
-    assert(isa<CallOpInterface>(callOp) && "expected a call-like user");
+    // If a non-call operation references the function (e.g. spirv.EntryPoint),
+    // we cannot safely remove arguments or return values since we don't know
+    // what the user expects. Skip this function entirely.
+    if (!isa<CallOpInterface>(callOp))
+      return;
     // Push an empty operand cleanup entry so that call-site specific logic in
     // cleanUpDeadVals runs (it keys off CallOpInterface). The BitVector is
     // intentionally all false to avoid generic erasure.
diff --git a/mlir/test/Transforms/remove-dead-values.mlir b/mlir/test/Transforms/remove-dead-values.mlir
index 87e77b2eb700f..7a08b2c94f0a8 100644
--- a/mlir/test/Transforms/remove-dead-values.mlir
+++ b/mlir/test/Transforms/remove-dead-values.mlir
@@ -826,3 +826,16 @@ func.func @replace_dead_operation_results_with_poison(%0: vector<1xindex>) -> ve
   }
   return %2 : vector<1xindex>
 }
+
+// -----
+
+// Verify no crash when a function is referenced by a non-call op (spirv.EntryPoint).
+// The function should be preserved as-is since the pass cannot analyse non-call users.
+// CHECK: spirv.EntryPoint "GLCompute" @main_func
+// CHECK: llvm.func @main_func()
+module {
+  spirv.EntryPoint "GLCompute" @main_func
+  llvm.func @main_func() attributes {sym_visibility = "private"} {
+    llvm.return
+  }
+}



More information about the Mlir-commits mailing list