@@ -70,6 +70,7 @@ llvm::cl::opt<bool> VerifyLifetimeCompletion("verify-lifetime-completion",
70
70
71
71
static SILInstruction *endOSSALifetime (SILValue value,
72
72
OSSACompleteLifetime::LifetimeEnd end,
73
+ bool nonDestroyingEnd,
73
74
SILBuilder &builder,
74
75
DeadEndBlocks &deb) {
75
76
auto loc =
@@ -82,7 +83,11 @@ static SILInstruction *endOSSALifetime(SILValue value,
82
83
if (value->getType ().is <SILBoxType>()) {
83
84
return builder.createDeallocBox (loc, value, isDeadEnd);
84
85
}
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
+ }
86
91
}
87
92
if (auto scopedAddress = ScopedAddressValue (value)) {
88
93
return scopedAddress.createScopeEnd (builder.getInsertionPoint (), loc);
@@ -95,6 +100,7 @@ static SILInstruction *endOSSALifetime(SILValue value,
95
100
96
101
static bool endLifetimeAtLivenessBoundary (SILValue value,
97
102
const SSAPrunedLiveness &liveness,
103
+ bool nonDestroyingEnd,
98
104
DeadEndBlocks &deb) {
99
105
PrunedLivenessBoundary boundary;
100
106
liveness.computeBoundary (boundary);
@@ -105,17 +111,17 @@ static bool endLifetimeAtLivenessBoundary(SILValue value,
105
111
PrunedLiveness::LifetimeEndingUse) {
106
112
changed = true ;
107
113
SILBuilderWithScope::insertAfter (
108
- lastUser, [value, &deb](SILBuilder &builder) {
114
+ lastUser, [value, &deb, nonDestroyingEnd ](SILBuilder &builder) {
109
115
endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary,
110
- builder, deb);
116
+ nonDestroyingEnd, builder, deb);
111
117
});
112
118
}
113
119
}
114
120
for (SILBasicBlock *edge : boundary.boundaryEdges ) {
115
121
changed = true ;
116
122
SILBuilderWithScope builder (edge->begin ());
117
- endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary, builder,
118
- deb);
123
+ endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary,\
124
+ nonDestroyingEnd, builder, deb);
119
125
}
120
126
for (SILNode *deadDef : boundary.deadDefs ) {
121
127
SILInstruction *next = nullptr ;
@@ -126,8 +132,8 @@ static bool endLifetimeAtLivenessBoundary(SILValue value,
126
132
}
127
133
changed = true ;
128
134
SILBuilderWithScope builder (next);
129
- endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary, builder,
130
- deb);
135
+ endOSSALifetime (value, OSSACompleteLifetime::LifetimeEnd::Boundary,
136
+ nonDestroyingEnd, builder, deb);
131
137
}
132
138
return changed;
133
139
}
@@ -465,12 +471,13 @@ void OSSACompleteLifetime::visitAvailabilityBoundary(
465
471
466
472
static bool endLifetimeAtAvailabilityBoundary (SILValue value,
467
473
const SSAPrunedLiveness &liveness,
474
+ bool nonDestroyingEnd,
468
475
DeadEndBlocks &deb) {
469
476
bool changed = false ;
470
477
OSSACompleteLifetime::visitAvailabilityBoundary (
471
478
value, liveness, [&](auto *unreachable, auto end) {
472
479
SILBuilderWithScope builder (unreachable);
473
- endOSSALifetime (value, end, builder, deb);
480
+ endOSSALifetime (value, end, nonDestroyingEnd, builder, deb);
474
481
changed = true ;
475
482
});
476
483
return changed;
@@ -479,15 +486,16 @@ static bool endLifetimeAtAvailabilityBoundary(SILValue value,
479
486
static bool endLifetimeAtBoundary (SILValue value,
480
487
SSAPrunedLiveness const &liveness,
481
488
OSSACompleteLifetime::Boundary boundary,
489
+ bool nonDestroyingEnd,
482
490
DeadEndBlocks &deadEndBlocks) {
483
491
bool changed = false ;
484
492
switch (boundary) {
485
493
case OSSACompleteLifetime::Boundary::Liveness:
486
- changed |= endLifetimeAtLivenessBoundary (value, liveness, deadEndBlocks);
494
+ changed |= endLifetimeAtLivenessBoundary (value, liveness, nonDestroyingEnd, deadEndBlocks);
487
495
break ;
488
496
case OSSACompleteLifetime::Boundary::Availability:
489
497
changed |=
490
- endLifetimeAtAvailabilityBoundary (value, liveness, deadEndBlocks);
498
+ endLifetimeAtAvailabilityBoundary (value, liveness, nonDestroyingEnd, deadEndBlocks);
491
499
break ;
492
500
}
493
501
return changed;
@@ -548,7 +556,7 @@ bool OSSACompleteLifetime::analyzeAndUpdateLifetime(
548
556
ASSERT (false && " caller must check for pointer escapes" );
549
557
}
550
558
return endLifetimeAtBoundary(scopedAddress.value, liveness, boundary,
551
- deadEndBlocks);
559
+ nonDestroyingEnd, deadEndBlocks);
552
560
}
553
561
554
562
// / End the lifetime of \p value at unreachable instructions.
@@ -572,7 +580,7 @@ bool OSSACompleteLifetime::analyzeAndUpdateLifetime(SILValue value,
572
580
LinearLiveness liveness (value);
573
581
liveness.compute ();
574
582
return endLifetimeAtBoundary (value, liveness.getLiveness (), boundary,
575
- deadEndBlocks);
583
+ nonDestroyingEnd, deadEndBlocks);
576
584
}
577
585
InteriorLiveness liveness (value);
578
586
liveness.compute (domInfo, handleInnerScope);
@@ -586,7 +594,7 @@ bool OSSACompleteLifetime::analyzeAndUpdateLifetime(SILValue value,
586
594
ASSERT (false && " caller must check for pointer escapes" );
587
595
}
588
596
return endLifetimeAtBoundary (value, liveness.getLiveness (), boundary,
589
- deadEndBlocks);
597
+ nonDestroyingEnd, deadEndBlocks);
590
598
}
591
599
592
600
namespace swift ::test {
@@ -598,16 +606,23 @@ namespace swift::test {
598
606
static FunctionTest OSSACompleteLifetimeTest (
599
607
" ossa_complete_lifetime" , [](auto &function, auto &arguments, auto &test) {
600
608
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
+ }
607
619
auto *deb = test.getDeadEndBlocks ();
608
620
llvm::outs () << " OSSA lifetime completion on " << kind
609
621
<< " boundary: " << value;
610
- OSSACompleteLifetime completion (&function, /* domInfo*/ nullptr , *deb);
622
+ OSSACompleteLifetime completion (&function, /* domInfo*/ nullptr , *deb,
623
+ OSSACompleteLifetime::IgnoreTrivialVariable,
624
+ /* forceLivenessVerification=*/ false ,
625
+ nonDestroyingEnd);
611
626
completion.completeOSSALifetime (value, kind);
612
627
function.print (llvm::outs ());
613
628
});
0 commit comments