From 91c2deacfef786e9ede9b88cfe0319fd68b0f71a Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Fri, 12 Dec 2025 16:11:13 +0100 Subject: [PATCH] SILCombine: don't sink forwarding instructions with address operands We don't do memory lifetime analysis for this peephole optimization. Therefore we can't risk sinking instructions with address operands out of the addressed memory's lifetime. For example: ``` %3 = mark_dependence %2 on %1 : $*T // must not be moved after the destroy_addr destroy_addr %1 ``` Fixes a verifier crash rdar://166240751 --- lib/SILOptimizer/SILCombiner/SILCombine.cpp | 17 +++++++++++++++++ test/SILOptimizer/sil_combine_ossa.sil | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp index 51eab585e2770..8669e569b9ad8 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp @@ -429,6 +429,14 @@ bool SILCombiner::doOneIteration(SILFunction &F, unsigned Iteration) { return MadeChange; } +static bool hasAddressOperands(SILInstruction *inst) { + for (Operand *op : inst->getRealOperands()) { + if (op->get()->getType().isAddress()) + return true; + } + return false; +} + void SILCombiner::processInstruction(SILInstruction *I, SILCombineCanonicalize &scCanonicalize, bool &MadeChange) { @@ -467,6 +475,15 @@ void SILCombiner::processInstruction(SILInstruction *I, if (auto *svi = dyn_cast(I)) { if (auto fwdOp = ForwardingOperation(svi)) { if (fwdOp.getSingleForwardingOperand() && + + // Don't risk sinking instructions with address operands out of the + // addressed memory's lifetime. E.g: + // ``` + // %3 = mark_dependence %2 on %1 : $*T // must not be moved after the destroy_addr + // destroy_addr %1 + // ``` + !hasAddressOperands(svi) && + SILValue(svi)->getOwnershipKind() == OwnershipKind::Owned) { // Try to sink the value. If we sank the value and deleted it, // return. If we didn't optimize or sank but we are still able to diff --git a/test/SILOptimizer/sil_combine_ossa.sil b/test/SILOptimizer/sil_combine_ossa.sil index d2d07af89bb97..5f3c2b82e89b2 100644 --- a/test/SILOptimizer/sil_combine_ossa.sil +++ b/test/SILOptimizer/sil_combine_ossa.sil @@ -5577,4 +5577,24 @@ bb0(%0 : @guaranteed $String): return %1 } +// CHECK-LABEL: sil [ossa] @dont_sink_mark_dependence_out_of_memory_lifetime : +// CHECK: mark_dependence +// CHECK: bb1: +// CHECK: } // end sil function 'dont_sink_mark_dependence_out_of_memory_lifetime' +sil [ossa] @dont_sink_mark_dependence_out_of_memory_lifetime : $@convention(thin) (@owned Klass, @owned Klass) -> () { +bb0(%0 : @owned $Klass, %1 : @owned $Klass): + %2 = alloc_stack $Klass + store %1 to [init] %2 + %4 = mark_dependence %0 on %2 + destroy_addr %2 + br bb1 + +bb1: + destroy_value %4 + dealloc_stack %2 + %9 = tuple () + return %9 +} + +