[Mlir-commits] [mlir] [mlir] Make remove-dead-values can delate useless function (PR #161471)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Tue Sep 30 18:56:18 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir-core

Author: lonely eagle (linuxlonelyeagle)

<details>
<summary>Changes</summary>

Fix https://github.com/llvm/llvm-project/issues/158760. If a private functionOpInterface has no users and there is no callOpInterface in its region, it is a useless function, and the remove-dead-values pass will delete this function.

---
Full diff: https://github.com/llvm/llvm-project/pull/161471.diff


2 Files Affected:

- (modified) mlir/lib/Transforms/RemoveDeadValues.cpp (+15-2) 
- (modified) mlir/test/Transforms/remove-dead-values.mlir (+15) 


``````````diff
diff --git a/mlir/lib/Transforms/RemoveDeadValues.cpp b/mlir/lib/Transforms/RemoveDeadValues.cpp
index e0c65b0e09774..18c6006f04788 100644
--- a/mlir/lib/Transforms/RemoveDeadValues.cpp
+++ b/mlir/lib/Transforms/RemoveDeadValues.cpp
@@ -297,6 +297,17 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module,
     return;
   }
 
+  // If a private function has neither users and function calls, it is a useless
+  // function.
+  SymbolTable::UseRange uses = *funcOp.getSymbolUses(module);
+  auto callSites = funcOp.getFunctionBody().getOps<CallOpInterface>();
+  if (uses.empty() && callSites.empty()) {
+    LDBG() << "Delete function op: "
+           << OpWithFlags(funcOp, OpPrintingFlags().skipRegions());
+    funcOp.erase();
+    return;
+  }
+
   // Get the list of unnecessary (non-live) arguments in `nonLiveArgs`.
   SmallVector<Value> arguments(funcOp.getArguments());
   BitVector nonLiveArgs = markLives(arguments, nonLiveSet, la);
@@ -312,7 +323,6 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module,
   // Do (2). (Skip creating generic operand cleanup entries for call ops.
   // Call arguments will be removed in the call-site specific segment-aware
   // cleanup, avoiding generic eraseOperands bitvector mechanics.)
-  SymbolTable::UseRange uses = *funcOp.getSymbolUses(module);
   for (SymbolTable::SymbolUse use : uses) {
     Operation *callOp = use.getUser();
     assert(isa<CallOpInterface>(callOp) && "expected a call-like user");
@@ -881,9 +891,12 @@ void RemoveDeadValues::runOnOperation() {
   // end of this pass.
   RDVFinalCleanupList finalCleanupList;
 
+  module->walk([&](FunctionOpInterface op) {
+    processFuncOp(op, module, la, deadVals, finalCleanupList);
+  });
   module->walk([&](Operation *op) {
     if (auto funcOp = dyn_cast<FunctionOpInterface>(op)) {
-      processFuncOp(funcOp, module, la, deadVals, finalCleanupList);
+      // The FunctionOpInterface has been processed in advance.
     } else if (auto regionBranchOp = dyn_cast<RegionBranchOpInterface>(op)) {
       processRegionBranchOp(regionBranchOp, la, deadVals, finalCleanupList);
     } else if (auto branchOp = dyn_cast<BranchOpInterface>(op)) {
diff --git a/mlir/test/Transforms/remove-dead-values.mlir b/mlir/test/Transforms/remove-dead-values.mlir
index 56449469dc29f..b8ad762c52ddf 100644
--- a/mlir/test/Transforms/remove-dead-values.mlir
+++ b/mlir/test/Transforms/remove-dead-values.mlir
@@ -649,3 +649,18 @@ func.func @callee(%arg0: index, %arg1: index, %arg2: index) -> index {
   %res = call @mutl_parameter(%arg0, %arg1, %arg2) : (index, index, index) -> (index)
   return %res : index
 }
+
+// -----
+
+// CHECK-NOT: func private @single_private_func 
+func.func private @single_private_func(%arg0: i64) -> (i64) {
+    %c0_i64 = arith.constant 0 : i64
+    %2 = arith.cmpi eq, %arg0, %c0_i64 : i64
+    cf.cond_br %2, ^bb1, ^bb2
+  ^bb1:  // pred: ^bb0
+    %c1_i64 = arith.constant 1 : i64
+    return %c1_i64 : i64
+  ^bb2:  // pred: ^bb0
+    %c3_i64 = arith.constant 3 : i64
+    return %c3_i64 : i64
+}
\ No newline at end of file

``````````

</details>


https://github.com/llvm/llvm-project/pull/161471


More information about the Mlir-commits mailing list