[Mlir-commits] [mlir] [mlir] Make eraseFunctionArguments fail instead of crash on used args (PR #203367)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Jun 11 12:00:33 PDT 2026


https://github.com/lijinpei-amd created https://github.com/llvm/llvm-project/pull/203367

Fixes https://github.com/llvm/llvm-project/issues/203218

Assisted-by: Claude (Claude Code)

>From a071dc3b97e3354c11550c0a9e4f6e8db9804ec3 Mon Sep 17 00:00:00 2001
From: Li Jinpei <jinpli at amd.com>
Date: Fri, 12 Jun 2026 02:43:40 +0800
Subject: [PATCH] [mlir] Make eraseFunctionArguments fail instead of crash on
 used args

Fixes https://github.com/llvm/llvm-project/issues/203218

Assisted-by: Claude (Claude Code)
---
 mlir/include/mlir/Interfaces/FunctionInterfaces.h |  8 +++++---
 .../include/mlir/Interfaces/FunctionInterfaces.td |  6 +++---
 mlir/lib/Interfaces/FunctionInterfaces.cpp        | 10 +++++++++-
 mlir/test/IR/test-func-erase-arg-error.mlir       | 15 +++++++++++++++
 4 files changed, 32 insertions(+), 7 deletions(-)
 create mode 100644 mlir/test/IR/test-func-erase-arg-error.mlir

diff --git a/mlir/include/mlir/Interfaces/FunctionInterfaces.h b/mlir/include/mlir/Interfaces/FunctionInterfaces.h
index e10e9bd342702..dd3d8605e44ff 100644
--- a/mlir/include/mlir/Interfaces/FunctionInterfaces.h
+++ b/mlir/include/mlir/Interfaces/FunctionInterfaces.h
@@ -67,9 +67,11 @@ void insertFunctionResults(FunctionOpInterface op,
                            ArrayRef<DictionaryAttr> resultAttrs,
                            unsigned originalNumResults, Type newType);
 
-/// Erase the specified arguments and update the function type attribute.
-void eraseFunctionArguments(FunctionOpInterface op, const BitVector &argIndices,
-                            Type newType);
+/// Erase the specified arguments and update the function type attribute. Returns
+/// failure if the function cannot be updated to have the new signature, e.g.
+/// because one of the erased arguments still has uses.
+LogicalResult eraseFunctionArguments(FunctionOpInterface op,
+                                     const BitVector &argIndices, Type newType);
 
 /// Erase the specified results and update the function type attribute.
 void eraseFunctionResults(FunctionOpInterface op,
diff --git a/mlir/include/mlir/Interfaces/FunctionInterfaces.td b/mlir/include/mlir/Interfaces/FunctionInterfaces.td
index f701e828ed641..371d9319e25e5 100644
--- a/mlir/include/mlir/Interfaces/FunctionInterfaces.td
+++ b/mlir/include/mlir/Interfaces/FunctionInterfaces.td
@@ -320,14 +320,14 @@ def FunctionOpInterface : OpInterface<"FunctionOpInterface", [
     }
 
     /// Erases the arguments listed in `argIndices`. Returns failure if the
-    /// function cannot be updated to have the new signature.
+    /// function cannot be updated to have the new signature, e.g. because one
+    /// of the erased arguments still has uses.
     ::llvm::LogicalResult eraseArguments(const ::llvm::BitVector &argIndices) {
       ::mlir::Type newType = $_op.getTypeWithoutArgs(argIndices);
       if (!newType)
         return ::llvm::failure();
-      ::mlir::function_interface_impl::eraseFunctionArguments(
+      return ::mlir::function_interface_impl::eraseFunctionArguments(
         $_op, argIndices, newType);
-      return ::llvm::success();
     }
 
     /// Erase a single result at `resultIndex`. Returns failure if the function
diff --git a/mlir/lib/Interfaces/FunctionInterfaces.cpp b/mlir/lib/Interfaces/FunctionInterfaces.cpp
index e0f1135e992ac..a096f8c642961 100644
--- a/mlir/lib/Interfaces/FunctionInterfaces.cpp
+++ b/mlir/lib/Interfaces/FunctionInterfaces.cpp
@@ -278,13 +278,20 @@ void function_interface_impl::insertFunctionResults(
   op.setFunctionTypeAttr(TypeAttr::get(newType));
 }
 
-void function_interface_impl::eraseFunctionArguments(
+LogicalResult function_interface_impl::eraseFunctionArguments(
     FunctionOpInterface op, const BitVector &argIndices, Type newType) {
   // There are 3 things that need to be updated:
   // - Function type.
   // - Arg attrs.
   // - Block arguments of entry block, if not empty.
 
+  if (!op.isExternal()) {
+    Block &entry = op->getRegion(0).front();
+    for (unsigned i : argIndices.set_bits())
+      if (!entry.getArgument(i).use_empty())
+        return failure();
+  }
+
   // Update the argument attributes of the function.
   if (ArrayAttr argAttrs = op.getArgAttrsAttr()) {
     SmallVector<DictionaryAttr, 4> newArgAttrs;
@@ -303,6 +310,7 @@ void function_interface_impl::eraseFunctionArguments(
     Block &entry = op->getRegion(0).front();
     entry.eraseArguments(argIndices);
   }
+  return success();
 }
 
 void function_interface_impl::eraseFunctionResults(
diff --git a/mlir/test/IR/test-func-erase-arg-error.mlir b/mlir/test/IR/test-func-erase-arg-error.mlir
new file mode 100644
index 0000000000000..4c2ecb762fe57
--- /dev/null
+++ b/mlir/test/IR/test-func-erase-arg-error.mlir
@@ -0,0 +1,15 @@
+// RUN: mlir-opt %s -test-func-erase-arg -split-input-file -verify-diagnostics
+
+// Erasing an argument that still has uses must fail gracefully instead of
+// crashing (see https://github.com/llvm/llvm-project/issues/203218).
+
+// expected-error @below {{failed to erase arguments}}
+func.func @f(%arg0: f32 {test.erase_this_arg}) -> f32 {
+  return %arg0 : f32
+}
+
+// -----
+
+// An external function has no body, so there are no argument uses to check and
+// erasure must succeed without crashing.
+func.func private @ext(f32 {test.erase_this_arg})



More information about the Mlir-commits mailing list