Fix assertion in InstructionDeleter::trackIfDead.

This assertion was triggering when deleting scope-ending operations whose
operand had been replaced with an undef:

   end_borrow undef

Related to rdar://156431548

This was triggered during simplify-cfg by after adding blocks to the worklist,
then later cleaning up dead instructions in the worklist blocks. I'm unable to
create a test case based on simplify-cfg because the assertion is completely
unrelated to the optimization that adds blocks to the worklist.
This commit is contained in:
Andrew Trick
2025-07-29 00:11:53 -07:00
parent ab8091964b
commit c1e0a1d999
2 changed files with 31 additions and 3 deletions

View File

@@ -187,9 +187,8 @@ bool InstructionDeleter::trackIfDead(SILInstruction *inst) {
bool fixLifetime = inst->getFunction()->hasOwnership();
if (isInstructionTriviallyDead(inst)
|| isScopeAffectingInstructionDead(inst, fixLifetime)) {
assert(!isIncidentalUse(inst) &&
(!isa<DestroyValueInst>(inst) ||
canTriviallyDeleteOSSAEndScopeInst(inst)) &&
assert(!isIncidentalUse(inst)
|| canTriviallyDeleteOSSAEndScopeInst(inst) &&
"Incidental uses cannot be removed in isolation. "
"They would be removed iff the operand is dead");
getCallbacks().notifyWillBeDeleted(inst);
@@ -356,6 +355,20 @@ static FunctionTest DeleterDeleteIfDeadTest(
llvm::outs() << "deleteIfDead returned " << deleted << "\n";
function.print(llvm::outs());
});
// Arguments:
// - instruction: the instruction to delete
// Dumps:
// - the function
static FunctionTest DeleterTrackIfDeadTest(
"deleter_track_if_dead", [](auto &function, auto &arguments, auto &test) {
auto *inst = arguments.takeInstruction();
InstructionDeleter deleter;
llvm::outs() << "Tracking " << *inst;
deleter.trackIfDead(inst);
deleter.cleanupDeadInstructions();
function.print(llvm::outs());
});
} // namespace swift::test
void InstructionDeleter::forceDeleteAndFixLifetimes(SILInstruction *inst) {

View File

@@ -57,3 +57,18 @@ sil [ossa] @doDeleteLoadTake : $() -> () {
%retval = tuple ()
return %retval : $()
}
// CHECK-LABEL: begin running test {{.*}} on trackEndBorrow
// CHECK: Tracking end_borrow undef : $C
// CHECK: sil [ossa] @trackEndBorrow : $@convention(thin) () -> () {
// CHECK: bb0:
// CHECK-NOT: end_borrow
// CHECK-LABEL: } // end sil function 'trackEndBorrow'
// CHECK-LABEL: end running test {{.*}} on trackEndBorrow
sil [ossa] @trackEndBorrow : $() -> () {
bb0:
specify_test "deleter_track_if_dead @instruction"
end_borrow undef : $C
%retval = tuple ()
return %retval : $()
}