[mlir] Make remove-dead-values remove block and successorOperands before delete ops (#166766)

Reland https://github.com/llvm/llvm-project/pull/165725, fix the Failed
test by removing successor operands before delete operations. Following
the deletion of cond.branch, its successor operands will subsequently be
removed.
This commit is contained in:
lonely eagle 2025-11-20 13:55:09 +08:00 committed by GitHub
parent b39a9db3ab
commit 765208b313
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 47 deletions

View File

@ -742,7 +742,49 @@ static void processBranchOp(BranchOpInterface branchOp, RunLivenessAnalysis &la,
static void cleanUpDeadVals(RDVFinalCleanupList &list) {
LDBG() << "Starting cleanup of dead values...";
// 1. Operations
// 1. Blocks, We must remove the block arguments and successor operands before
// deleting the operation, as they may reside in the region operation.
LDBG() << "Cleaning up " << list.blocks.size() << " block argument lists";
for (auto &b : list.blocks) {
// 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) {
if (!b.nonLiveArgs[i])
continue;
LDBG() << " Erasing block argument " << i << ": " << b.b->getArgument(i);
b.b->getArgument(i).dropAllUses();
b.b->eraseArgument(i);
}
}
// 2. Successor Operands
LDBG() << "Cleaning up " << list.successorOperands.size()
<< " successor operand lists";
for (auto &op : list.successorOperands) {
SuccessorOperands successorOperands =
op.branch.getSuccessorOperands(op.successorIndex);
// 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());
// 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);
}
}
// 3. Operations
LDBG() << "Cleaning up " << list.operations.size() << " operations";
for (auto &op : list.operations) {
LDBG() << "Erasing operation: "
@ -751,14 +793,14 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
op->erase();
}
// 2. Values
// 4. Values
LDBG() << "Cleaning up " << list.values.size() << " values";
for (auto &v : list.values) {
LDBG() << "Dropping all uses of value: " << v;
v.dropAllUses();
}
// 3. Functions
// 5. Functions
LDBG() << "Cleaning up " << list.functions.size() << " functions";
// Record which function arguments were erased so we can shrink call-site
// argument segments for CallOpInterface operations (e.g. ops using
@ -780,7 +822,7 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
(void)f.funcOp.eraseResults(f.nonLiveRets);
}
// 4. Operands
// 6. Operands
LDBG() << "Cleaning up " << list.operands.size() << " operand lists";
for (OperationToCleanup &o : list.operands) {
// Handle call-specific cleanup only when we have a cached callee reference.
@ -822,7 +864,7 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
}
}
// 5. Results
// 7. Results
LDBG() << "Cleaning up " << list.results.size() << " result lists";
for (auto &r : list.results) {
LDBG() << "Erasing " << r.nonLive.count()
@ -830,48 +872,6 @@ static void cleanUpDeadVals(RDVFinalCleanupList &list) {
<< OpWithFlags(r.op, OpPrintingFlags().skipRegions());
dropUsesAndEraseResults(r.op, r.nonLive);
}
// 6. Blocks
LDBG() << "Cleaning up " << list.blocks.size() << " block argument lists";
for (auto &b : list.blocks) {
// 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) {
if (!b.nonLiveArgs[i])
continue;
LDBG() << " Erasing block argument " << i << ": " << b.b->getArgument(i);
b.b->getArgument(i).dropAllUses();
b.b->eraseArgument(i);
}
}
// 7. Successor Operands
LDBG() << "Cleaning up " << list.successorOperands.size()
<< " successor operand lists";
for (auto &op : list.successorOperands) {
SuccessorOperands successorOperands =
op.branch.getSuccessorOperands(op.successorIndex);
// 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());
// 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);
}
}
LDBG() << "Finished cleanup of dead values";
}

View File

@ -674,3 +674,16 @@ func.func @dead_value_loop_ivs_no_result(%lb: index, %ub: index, %step: index, %
}
return
}
// -----
// CHECK-LABEL: func @op_block_have_dead_arg
func.func @op_block_have_dead_arg(%arg0: index, %arg1: index, %arg2: i1) {
scf.execute_region {
cf.cond_br %arg2, ^bb1(%arg0 : index), ^bb1(%arg1 : index)
^bb1(%0: index):
scf.yield
}
// CHECK-NEXT: return
return
}