[Mlir-commits] [mlir] [mlir][CSE] fix use-after-free (PR #203849)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Jun 15 01:56:00 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Stefan Schuermans (schuermans-roofline)

<details>
<summary>Changes</summary>

There was a use-after free introduced accidentally by e79e056ee982 [mlir][CSE] Remove the opsToErase container and immediately delete dead ops. (#<!-- -->203702) This change fixes it.

Locating the use-after-free has been assisted by Claude Code. The implementation of the fix has been done without it.

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


1 Files Affected:

- (modified) mlir/lib/Transforms/Utils/CSE.cpp (+10-5) 


``````````diff
diff --git a/mlir/lib/Transforms/Utils/CSE.cpp b/mlir/lib/Transforms/Utils/CSE.cpp
index eed77f20dd2da..a5cc2376f4ba8 100644
--- a/mlir/lib/Transforms/Utils/CSE.cpp
+++ b/mlir/lib/Transforms/Utils/CSE.cpp
@@ -126,14 +126,15 @@ void CSEDriver::replaceUsesAndDelete(ScopedMapTy &knownValues, Operation *op,
                                      Operation *existing,
                                      bool hasSSADominance) {
   // If we find one then replace all uses of the current operation with the
-  // existing one and mark it for deletion. We can only replace an operand in
-  // an operation if it has not been visited yet.
+  // existing one and mark it for deletion at the bottom of the function. We
+  // can only replace an operand in an operation if it has not been visited yet.
+  bool opIsDead = false;
   if (hasSSADominance) {
     // If the region has SSA dominance, then we are guaranteed to have not
     // visited any use of the current operation.
     // Replace all uses, but do not remove the operation yet.
     rewriter.replaceAllOpUsesWith(op, existing->getResults());
-    eraseDeadOp(op);
+    opIsDead = true;
   } else {
     // When the region does not have SSA dominance, we need to check if we
     // have visited a use before replacing any use.
@@ -152,8 +153,7 @@ void CSEDriver::replaceUsesAndDelete(ScopedMapTy &knownValues, Operation *op,
                                wasVisited);
 
     // There may be some remaining uses of the operation.
-    if (op->use_empty())
-      eraseDeadOp(op);
+    opIsDead = op->use_empty();
   }
 
   // If the existing operation has an unknown location and the current
@@ -162,6 +162,11 @@ void CSEDriver::replaceUsesAndDelete(ScopedMapTy &knownValues, Operation *op,
   if (isa<UnknownLoc>(existing->getLoc()) && !isa<UnknownLoc>(op->getLoc()))
     existing->setLoc(op->getLoc());
 
+  // Deletion of the dead current op can only be done here, and not before,
+  // because the its location is still read above.
+  if (opIsDead)
+    eraseDeadOp(op);
+
   ++numCSE;
 }
 

``````````

</details>


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


More information about the Mlir-commits mailing list