[Mlir-commits] [mlir] [mlir] Use wouldOpBeTriviallyDead in LivenessAnalysis (PR #174362)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sun Jan 4 22:18:31 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: None (neildhar)

<details>
<summary>Changes</summary>

`wouldOpBeTriviallyDead` is closer to the intended purpose here, and aligns the code with how the greedy pattern rewriter identifies dead operations.

Importantly, it allows us to identify unused read-only memory operations, which would previously have failed the `isMemoryEffectFree` check.

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


2 Files Affected:

- (modified) mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp (+2-2) 
- (modified) mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir (+23-3) 


``````````diff
diff --git a/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp b/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp
index ec7fec86f0c51..25d58c99c1ae7 100644
--- a/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/LivenessAnalysis.cpp
@@ -82,7 +82,7 @@ LivenessAnalysis::visitOperation(Operation *op, ArrayRef<Liveness *> operands,
   LDBG() << "[visitOperation] Enter: "
          << OpWithFlags(op, OpPrintingFlags().skipRegions());
   // This marks values of type (1.a) and (4) liveness as "live".
-  if (!isMemoryEffectFree(op) || op->hasTrait<OpTrait::ReturnLike>()) {
+  if (!wouldOpBeTriviallyDead(op)) {
     LDBG() << "[visitOperation] Operation has memory effects or is "
               "return-like, marking operands live";
     for (auto *operand : operands) {
@@ -210,7 +210,7 @@ void LivenessAnalysis::visitBranchOperand(OpOperand &operand) {
     if (mayLive)
       break;
     for (Operation &nestedOp : *block) {
-      if (!isMemoryEffectFree(&nestedOp)) {
+      if (!wouldOpBeTriviallyDead(&nestedOp)) {
         mayLive = true;
         LDBG() << "Non-forwarded branch operand may be "
                   "live due to memory effect in block: "
diff --git a/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir b/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir
index 171a35fdeafb9..a3cd10f785b1d 100644
--- a/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir
+++ b/mlir/test/Analysis/DataFlow/test-liveness-analysis.mlir
@@ -336,7 +336,7 @@ func.func @affine_loop_no_use_iv_has_side_effect_op() {
 // CHECK-NEXT: region: #0:
 // CHECK-NEXT:   argument: #0: not live
 func.func @affine_loop_no_use_iv() {
-  affine.for %arg0 = 0 to 79 { 
+  affine.for %arg0 = 0 to 79 {
   } {tag = "for"}
   return
 }
@@ -351,9 +351,29 @@ func.func @affine_loop_no_use_iv() {
 func.func @forall_no_use_iv_has_side_effect_op(%idx1: index, %idx2: index) {
   scf.parallel (%i) = (%idx1) to (%idx2) step (%idx2) {
     %r = memref.alloca() : memref<10xf32>
+    %cst = arith.constant 0.0 : f32
     scf.forall (%e2) in (%idx2) {
-      %a = memref.load %r[%idx2] : memref<10xf32>
+      memref.store %cst, %r[%idx2] : memref<10xf32>
     } {tag = "forall"}
-  } 
+  }
+  return
+}
+
+// -----
+
+// CHECK-LABEL: test_tag: for:
+// CHECK-NEXT:   operand #0: not live
+// CHECK-NEXT:   operand #1: not live
+// CHECK-NEXT:   operand #2: not live
+// CHECK-NEXT:   operand #3: not live
+
+func.func @test_for_loop_read_only(%arg0: memref<10xindex>) {
+  %c0 = arith.constant 0 : index
+  %c10 = arith.constant 10 : index
+  %c1 = arith.constant 1 : index
+  %0 = scf.for %iv = %c0 to %c10 step %c1 iter_args(%idx = %c0) -> (index) {
+    %loaded = memref.load %arg0[%idx] : memref<10xindex>
+    scf.yield %loaded : index
+  } {tag = "for"}
   return
 }

``````````

</details>


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


More information about the Mlir-commits mailing list