[Mlir-commits] [mlir] [mlir][Transforms][NFC] Improve debug output of `-remove-dead-values` (PR #173468)
Matthias Springer
llvmlistbot at llvm.org
Wed Dec 24 02:17:07 PST 2025
https://github.com/matthias-springer updated https://github.com/llvm/llvm-project/pull/173468
>From b057a2d858452534951600b04948f86c13ee54a6 Mon Sep 17 00:00:00 2001
From: Matthias Springer <me at m-sp.org>
Date: Wed, 24 Dec 2025 09:09:31 +0000
Subject: [PATCH] [mlir][Transforms][NFC] Improve debug output of
`-remove-dead-values`
---
mlir/lib/Transforms/RemoveDeadValues.cpp | 102 +++++++++++++++--------
1 file changed, 66 insertions(+), 36 deletions(-)
diff --git a/mlir/lib/Transforms/RemoveDeadValues.cpp b/mlir/lib/Transforms/RemoveDeadValues.cpp
index e9ced064c9884..1b3a5c6978849 100644
--- a/mlir/lib/Transforms/RemoveDeadValues.cpp
+++ b/mlir/lib/Transforms/RemoveDeadValues.cpp
@@ -268,7 +268,8 @@ static void processSimpleOp(Operation *op, RunLivenessAnalysis &la,
markLives(op->getOperands(), nonLiveSet, la).flip().any();
if (hasDeadOperand) {
LDBG() << "Simple op has dead operands, so the op must be dead: "
- << OpWithFlags(op, OpPrintingFlags().skipRegions());
+ << OpWithFlags(op,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
assert(!hasLive(op->getResults(), nonLiveSet, la) &&
"expected the op to have no live results");
cl.operations.push_back(op);
@@ -280,14 +281,15 @@ static void processSimpleOp(Operation *op, RunLivenessAnalysis &la,
if (!isMemoryEffectFree(op) || hasLive(op->getResults(), nonLiveSet, la)) {
LDBG() << "Simple op is not memory effect free or has live results, "
"preserving it: "
- << OpWithFlags(op, OpPrintingFlags().skipRegions());
+ << OpWithFlags(op,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
return;
}
LDBG()
<< "Simple op has all dead results and is memory effect free, scheduling "
"for removal: "
- << OpWithFlags(op, OpPrintingFlags().skipRegions());
+ << OpWithFlags(op, OpPrintingFlags().skipRegions().printGenericOpForm());
cl.operations.push_back(op);
collectNonLiveValues(nonLiveSet, op->getResults(),
BitVector(op->getNumResults(), true));
@@ -307,7 +309,8 @@ static void processFuncOp(FunctionOpInterface funcOp, Operation *module,
RunLivenessAnalysis &la, DenseSet<Value> &nonLiveSet,
RDVFinalCleanupList &cl) {
LDBG() << "Processing function op: "
- << OpWithFlags(funcOp, OpPrintingFlags().skipRegions());
+ << OpWithFlags(funcOp,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
if (funcOp.isPublic() || funcOp.isExternal()) {
LDBG() << "Function is public or external, skipping: "
<< funcOp.getOperation()->getName();
@@ -432,7 +435,21 @@ static void processRegionBranchOp(RegionBranchOpInterface regionBranchOp,
DenseSet<Value> &nonLiveSet,
RDVFinalCleanupList &cl) {
LDBG() << "Processing region branch op: "
- << OpWithFlags(regionBranchOp, OpPrintingFlags().skipRegions());
+ << OpWithFlags(regionBranchOp,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
+
+ // Scenario 1. This is the only case where the entire `regionBranchOp`
+ // is removed. It will not happen in any other scenario. Note that in this
+ // case, a non-forwarded operand of `regionBranchOp` could be live/non-live.
+ // It could never be live because of this op but its liveness could have been
+ // attributed to something else.
+ // Do (1') and (2').
+ if (isMemoryEffectFree(regionBranchOp.getOperation()) &&
+ !hasLive(regionBranchOp->getResults(), nonLiveSet, la)) {
+ cl.operations.push_back(regionBranchOp.getOperation());
+ return;
+ }
+
// Mark live results of `regionBranchOp` in `liveResults`.
auto markLiveResults = [&](BitVector &liveResults) {
liveResults = markLives(regionBranchOp->getResults(), nonLiveSet, la);
@@ -642,18 +659,6 @@ static void processRegionBranchOp(RegionBranchOpInterface regionBranchOp,
}
};
- // Scenario 1. This is the only case where the entire `regionBranchOp`
- // is removed. It will not happen in any other scenario. Note that in this
- // case, a non-forwarded operand of `regionBranchOp` could be live/non-live.
- // It could never be live because of this op but its liveness could have been
- // attributed to something else.
- // Do (1') and (2').
- if (isMemoryEffectFree(regionBranchOp.getOperation()) &&
- !hasLive(regionBranchOp->getResults(), nonLiveSet, la)) {
- cl.operations.push_back(regionBranchOp.getOperation());
- return;
- }
-
// Scenario 2.
// At this point, we know that every non-forwarded operand of `regionBranchOp`
// is live.
@@ -787,13 +792,19 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
// blocks that are accessed via multiple codepaths processed once
if (b.b->getNumArguments() != b.nonLiveArgs.size())
continue;
- LDBG() << "Erasing " << b.nonLiveArgs.count()
- << " non-live arguments from block: " << b.b;
- // it iterates backwards because erase invalidates all successor indexes
- for (int i = b.nonLiveArgs.size() - 1; i >= 0; --i) {
+ LDBG_OS([&](raw_ostream &os) {
+ os << "Erasing non-live arguments [";
+ llvm::interleaveComma(b.nonLiveArgs.set_bits(), os);
+ os << "] from block: " << b.b << " in region "
+ << b.b->getParent()->getRegionNumber() << " of operation "
+ << OpWithFlags(b.b->getParent()->getParentOp(),
+ OpPrintingFlags().skipRegions().printGenericOpForm());
+ });
+ // Note: Iterate from the end to make sure that that indices of not yet
+ // processes arguments do not change.
+ for (auto i : b.nonLiveArgs.set_bits()) {
if (!b.nonLiveArgs[i])
continue;
- LDBG() << " Erasing block argument " << i << ": " << b.b->getArgument(i);
b.b->getArgument(i).dropAllUses();
b.b->eraseArgument(i);
}
@@ -808,16 +819,17 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
// blocks that are accessed via multiple codepaths processed once
if (successorOperands.size() != op.nonLiveOperands.size())
continue;
- LDBG() << "Erasing " << op.nonLiveOperands.count()
- << " non-live successor operands from successor "
- << op.successorIndex << " of branch: "
- << OpWithFlags(op.branch, OpPrintingFlags().skipRegions());
+ LDBG_OS([&](raw_ostream &os) {
+ os << "Erasing non-live successor operands [";
+ llvm::interleaveComma(op.nonLiveOperands.set_bits(), os);
+ os << "] from successor " << op.successorIndex << " of branch: "
+ << OpWithFlags(op.branch.getOperation(),
+ OpPrintingFlags().skipRegions().printGenericOpForm());
+ });
// it iterates backwards because erase invalidates all successor indexes
for (int i = successorOperands.size() - 1; i >= 0; --i) {
if (!op.nonLiveOperands[i])
continue;
- LDBG() << " Erasing successor operand " << i << ": "
- << successorOperands[i];
successorOperands.erase(i);
}
}
@@ -826,7 +838,8 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
LDBG() << "Cleaning up " << list.operations.size() << " operations";
for (Operation *op : list.operations) {
LDBG() << "Erasing operation: "
- << OpWithFlags(op, OpPrintingFlags().skipRegions());
+ << OpWithFlags(op,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
if (op->hasTrait<OpTrait::IsTerminator>()) {
// When erasing a terminator, insert an unreachable op in its place.
OpBuilder b(op);
@@ -850,10 +863,16 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
// AttrSizedOperandSegments) in the next phase.
DenseMap<Operation *, BitVector> erasedFuncArgs;
for (auto &f : list.functions) {
- LDBG() << "Cleaning up function: " << f.funcOp.getOperation()->getName();
- LDBG() << " Erasing " << f.nonLiveArgs.count() << " non-live arguments";
- LDBG() << " Erasing " << f.nonLiveRets.count()
- << " non-live return values";
+ LDBG() << "Cleaning up function: " << f.funcOp.getOperation()->getName()
+ << " (" << f.funcOp.getOperation() << ")";
+ LDBG_OS([&](raw_ostream &os) {
+ os << " Erasing non-live arguments [";
+ llvm::interleaveComma(f.nonLiveArgs.set_bits(), os);
+ os << "]\n";
+ os << " Erasing non-live return values [";
+ llvm::interleaveComma(f.nonLiveRets.set_bits(), os);
+ os << "]";
+ });
// Some functions may not allow erasing arguments or results. These calls
// return failure in such cases without modifying the function, so it's okay
// to proceed.
@@ -903,6 +922,13 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
// - Call operations without cached callee (where handledAsCall is false)
// But skip call operations that were already handled via segment-aware path
if (!handledAsCall && o.nonLive.any()) {
+ LDBG_OS([&](raw_ostream &os) {
+ os << "Erasing non-live operands [";
+ llvm::interleaveComma(o.nonLive.set_bits(), os);
+ os << "] from operation: "
+ << OpWithFlags(o.op,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
+ });
o.op->eraseOperands(o.nonLive);
}
}
@@ -910,9 +936,13 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
// 7. Results
LDBG() << "Cleaning up " << list.results.size() << " result lists";
for (auto &r : list.results) {
- LDBG() << "Erasing " << r.nonLive.count()
- << " non-live results from operation: "
- << OpWithFlags(r.op, OpPrintingFlags().skipRegions());
+ LDBG_OS([&](raw_ostream &os) {
+ os << "Erasing non-live results [";
+ llvm::interleaveComma(r.nonLive.set_bits(), os);
+ os << "] from operation: "
+ << OpWithFlags(r.op,
+ OpPrintingFlags().skipRegions().printGenericOpForm());
+ });
dropUsesAndEraseResults(r.op, r.nonLive);
}
LDBG() << "Finished cleanup of dead values";
More information about the Mlir-commits
mailing list