@@ -70,6 +70,7 @@ llvm::cl::opt<bool> VerifyLifetimeCompletion("verify-lifetime-completion",
7070
7171static SILInstruction *endOSSALifetime (SILValue value,
7272 OSSACompleteLifetime::LifetimeEnd end,
73+ bool nonDestroyingEnd,
7374 SILBuilder &builder,
7475 DeadEndBlocks &deb) {
7576 auto loc =
@@ -82,7 +83,11 @@ static SILInstruction *endOSSALifetime(SILValue value,
8283 if (value->getType ().is <SILBoxType>()) {
8384 return builder.createDeallocBox (loc, value, isDeadEnd);
8485 }
85- return builder.createDestroyValue (loc, value, DontPoisonRefs, isDeadEnd);
86+ if (nonDestroyingEnd && !isDeadEnd) {
87+ return builder.createEndLifetime (loc, value);
88+ } else {
89+ return builder.createDestroyValue (loc, value, DontPoisonRefs, isDeadEnd);
90+ }
8691 }
8792 if (auto scopedAddress = ScopedAddressValue (value)) {
8893 return scopedAddress.createScopeEnd (builder.getInsertionPoint (), loc);
@@ -95,6 +100,7 @@ static SILInstruction *endOSSALifetime(SILValue value,
95100
96101static bool endLifetimeAtLivenessBoundary (SILValue value,
97102 const SSAPrunedLiveness &liveness,
103+ bool nonDestroyingEnd,
98104 DeadEndBlocks &deb) {
99105 PrunedLivenessBoundary boundary;
100106 liveness.computeBoundary (boundary);
@@ -105,17 +111,17 @@ static bool endLifetimeAtLivenessBoundary(SILValue value,
105111 PrunedLiveness::LifetimeEndingUse) {
106112 changed = true ;
107113 SILBuilderWithScope::insertAfter (
108- lastUser, [value, &deb](SILBuilder &builder) {
114+ lastUser, [value, &deb, nonDestroyingEnd ](SILBuilder &builder) {
109115 endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary,
110- builder, deb);
116+ nonDestroyingEnd, builder, deb);
111117 });
112118 }
113119 }
114120 for (SILBasicBlock *edge : boundary.boundaryEdges ) {
115121 changed = true ;
116122 SILBuilderWithScope builder (edge->begin ());
117- endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary, builder,
118- deb);
123+ endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary,\
124+ nonDestroyingEnd, builder, deb);
119125 }
120126 for (SILNode *deadDef : boundary.deadDefs ) {
121127 SILInstruction *next = nullptr ;
@@ -126,8 +132,8 @@ static bool endLifetimeAtLivenessBoundary(SILValue value,
126132 }
127133 changed = true ;
128134 SILBuilderWithScope builder (next);
129- endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary, builder,
130- deb);
135+ endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary,
136+ nonDestroyingEnd, builder, deb);
131137 }
132138 return changed;
133139}
@@ -465,12 +471,13 @@ void OSSACompleteLifetime::visitAvailabilityBoundary(
465471
466472static bool endLifetimeAtAvailabilityBoundary (SILValue value,
467473 const SSAPrunedLiveness &liveness,
474+ bool nonDestroyingEnd,
468475 DeadEndBlocks &deb) {
469476 bool changed = false ;
470477 OSSACompleteLifetime::visitAvailabilityBoundary (
471478 value, liveness, [&](auto *unreachable, auto end) {
472479 SILBuilderWithScope builder (unreachable);
473- endOSSALifetime (value, end, builder, deb);
480+ endOSSALifetime (value, end, nonDestroyingEnd, builder, deb);
474481 changed = true ;
475482 });
476483 return changed;
@@ -479,15 +486,16 @@ static bool endLifetimeAtAvailabilityBoundary(SILValue value,
479486static bool endLifetimeAtBoundary (SILValue value,
480487 SSAPrunedLiveness const &liveness,
481488 OSSACompleteLifetime::Boundary boundary,
489+ bool nonDestroyingEnd,
482490 DeadEndBlocks &deadEndBlocks) {
483491 bool changed = false ;
484492 switch (boundary) {
485493 case OSSACompleteLifetime::Boundary::Liveness:
486- changed |= endLifetimeAtLivenessBoundary (value, liveness, deadEndBlocks);
494+ changed |= endLifetimeAtLivenessBoundary (value, liveness, nonDestroyingEnd, deadEndBlocks);
487495 break ;
488496 case OSSACompleteLifetime::Boundary::Availability:
489497 changed |=
490- endLifetimeAtAvailabilityBoundary (value, liveness, deadEndBlocks);
498+ endLifetimeAtAvailabilityBoundary (value, liveness, nonDestroyingEnd, deadEndBlocks);
491499 break ;
492500 }
493501 return changed;
@@ -548,7 +556,7 @@ bool OSSACompleteLifetime::analyzeAndUpdateLifetime(
548556 ASSERT (false && " caller must check for pointer escapes" );
549557 }
550558 return endLifetimeAtBoundary(scopedAddress.value, liveness, boundary,
551- deadEndBlocks);
559+ nonDestroyingEnd, deadEndBlocks);
552560}
553561
554562// / End the lifetime of \p value at unreachable instructions.
@@ -572,7 +580,7 @@ bool OSSACompleteLifetime::analyzeAndUpdateLifetime(SILValue value,
572580 LinearLiveness liveness (value);
573581 liveness.compute ();
574582 return endLifetimeAtBoundary (value, liveness.getLiveness (), boundary,
575- deadEndBlocks);
583+ nonDestroyingEnd, deadEndBlocks);
576584 }
577585 InteriorLiveness liveness (value);
578586 liveness.compute (domInfo, handleInnerScope);
@@ -586,7 +594,7 @@ bool OSSACompleteLifetime::analyzeAndUpdateLifetime(SILValue value,
586594 ASSERT (false && " caller must check for pointer escapes" );
587595 }
588596 return endLifetimeAtBoundary (value, liveness.getLiveness (), boundary,
589- deadEndBlocks);
597+ nonDestroyingEnd, deadEndBlocks);
590598}
591599
592600namespace swift ::test {
@@ -598,16 +606,23 @@ namespace swift::test {
598606static FunctionTest OSSACompleteLifetimeTest (
599607 " ossa_complete_lifetime" , [](auto &function, auto &arguments, auto &test) {
600608 SILValue value = arguments.takeValue ();
601- OSSACompleteLifetime::Boundary kind =
602- llvm::StringSwitch<OSSACompleteLifetime::Boundary>(
603- arguments.takeString ())
604- .Case (" liveness" , OSSACompleteLifetime::Boundary::Liveness)
605- .Case (" availability" ,
606- OSSACompleteLifetime::Boundary::Availability);
609+ OSSACompleteLifetime::Boundary kind = OSSACompleteLifetime::Boundary::Liveness;
610+ bool nonDestroyingEnd = false ;
611+ StringRef kindArg = arguments.takeString ();
612+ if (kindArg == " liveness_no_destroy" ) {
613+ nonDestroyingEnd = true ;
614+ } else if (kindArg == " availability" ) {
615+ kind = OSSACompleteLifetime::Boundary::Availability;
616+ } else {
617+ assert (kindArg == " liveness" );
618+ }
607619 auto *deb = test.getDeadEndBlocks ();
608620 llvm::outs () << " OSSA lifetime completion on " << kind
609621 << " boundary: " << value;
610- OSSACompleteLifetime completion (&function, /* domInfo*/ nullptr , *deb);
622+ OSSACompleteLifetime completion (&function, /* domInfo*/ nullptr , *deb,
623+ OSSACompleteLifetime::IgnoreTrivialVariable,
624+ /* forceLivenessVerification=*/ false ,
625+ nonDestroyingEnd);
611626 completion.completeOSSALifetime (value, kind);
612627 function.print (llvm::outs ());
613628 });
0 commit comments