@@ -203,6 +203,7 @@ class DCE {
203203
204204 void markValueLive (SILValue V);
205205 void markInstructionLive (SILInstruction *Inst);
206+ void markOwnedDeadValueLive (SILValue v);
206207 void markTerminatorArgsLive (SILBasicBlock *Pred, SILBasicBlock *Succ,
207208 size_t ArgIndex);
208209 void markControllingTerminatorsLive (SILBasicBlock *Block);
@@ -265,6 +266,20 @@ void DCE::markInstructionLive(SILInstruction *Inst) {
265266 Worklist.push_back (Inst);
266267}
267268
269+ void DCE::markOwnedDeadValueLive (SILValue v) {
270+ if (v->getOwnershipKind () == OwnershipKind::Owned) {
271+ // When an owned value has no lifetime ending uses it means that it is in a
272+ // dead-end region. We must not remove and inserting compensating destroys
273+ // for it because that would potentially destroy the value too early.
274+ // TODO: we can remove this once we have complete OSSA lifetimes
275+ for (Operand *use : v->getUses ()) {
276+ if (use->isLifetimeEnding ())
277+ return ;
278+ }
279+ markValueLive (v);
280+ }
281+ }
282+
268283// / Gets the producing instruction of a cond_fail condition. Currently these
269284// / are overflow builtins but may be extended to other instructions in the
270285// / future.
@@ -331,6 +346,9 @@ void DCE::markLive() {
331346 // to be live in the sense that they are not trivially something we
332347 // can delete by examining only that instruction.
333348 for (auto &BB : *F) {
349+ for (SILArgument *arg : BB.getArguments ()) {
350+ markOwnedDeadValueLive (arg);
351+ }
334352 for (auto &I : BB) {
335353 switch (I.getKind ()) {
336354 case SILInstructionKind::CondFailInst: {
@@ -395,6 +413,9 @@ void DCE::markLive() {
395413 default :
396414 if (seemsUseful (&I))
397415 markInstructionLive (&I);
416+ for (SILValue result : I.getResults ()) {
417+ markOwnedDeadValueLive (result);
418+ }
398419 }
399420 }
400421 }
0 commit comments