From ab8091964b0bee01bd3002ebbe049e12263c76aa Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 29 Jul 2025 00:10:59 -0700 Subject: [PATCH 1/2] [NFC] add SinkAddressProjections::dump() --- .../swift/SILOptimizer/Utils/BasicBlockOptUtils.h | 2 ++ lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h index d7402cc809e05..0568861f61f92 100644 --- a/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h +++ b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h @@ -164,6 +164,8 @@ class SinkAddressProjections { /// /// getInBlockProjectionOperandValues() can be called before or after cloning. bool cloneProjections(); + + SWIFT_DEBUG_DUMP; }; /// Clone a single basic block and any required successor edges within the same diff --git a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp index 32bf17da930df..757e2329f1e29 100644 --- a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp +++ b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp @@ -285,3 +285,16 @@ bool SinkAddressProjections::cloneProjections() { } return true; } + +void SinkAddressProjections::dump() const { + llvm::dbgs() << "Old projections: "; + for (auto *proj : oldProjections) { + proj->dump(); + } + if (auto *np = newProjections) { + llvm::dbgs() << "New projections: "; + for (auto *proj : *np) { + proj->dump(); + } + } +} From c1e0a1d9990f317c35f5543b0e3dbd5930551cf8 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 29 Jul 2025 00:11:53 -0700 Subject: [PATCH 2/2] 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. --- lib/SILOptimizer/Utils/InstructionDeleter.cpp | 19 ++++++++++++++++--- test/SILOptimizer/instruction_deleter.sil | 15 +++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/SILOptimizer/Utils/InstructionDeleter.cpp b/lib/SILOptimizer/Utils/InstructionDeleter.cpp index f7d4761b23a4d..ffefbc874ac46 100644 --- a/lib/SILOptimizer/Utils/InstructionDeleter.cpp +++ b/lib/SILOptimizer/Utils/InstructionDeleter.cpp @@ -187,9 +187,8 @@ bool InstructionDeleter::trackIfDead(SILInstruction *inst) { bool fixLifetime = inst->getFunction()->hasOwnership(); if (isInstructionTriviallyDead(inst) || isScopeAffectingInstructionDead(inst, fixLifetime)) { - assert(!isIncidentalUse(inst) && - (!isa(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) { diff --git a/test/SILOptimizer/instruction_deleter.sil b/test/SILOptimizer/instruction_deleter.sil index bb50d8c2f2627..91ea283b07967 100644 --- a/test/SILOptimizer/instruction_deleter.sil +++ b/test/SILOptimizer/instruction_deleter.sil @@ -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 : $() +}