@@ -390,6 +390,7 @@ namespace {
390
390
SmallVectorImpl<DIMemoryUse> &Uses;
391
391
TinyPtrVector<SILInstruction *> &StoresToSelf;
392
392
SmallVectorImpl<SILInstruction *> &Destroys;
393
+ SmallVector<unsigned , 8 > NeedsUpdateForInitState;
393
394
std::vector<ConditionalDestroy> ConditionalDestroys;
394
395
395
396
llvm::SmallDenseMap<SILBasicBlock*, LiveOutBlockState, 32 > PerBlockInfo;
@@ -459,7 +460,7 @@ namespace {
459
460
460
461
461
462
void handleStoreUse (unsigned UseID);
462
- void handleLoadUse (unsigned UseID );
463
+ void handleLoadUse (const DIMemoryUse &Use );
463
464
void handleLoadForTypeOfSelfUse (const DIMemoryUse &Use);
464
465
void handleInOutUse (const DIMemoryUse &Use);
465
466
void handleEscapeUse (const DIMemoryUse &Use);
@@ -471,7 +472,8 @@ namespace {
471
472
bool SuperInitDone,
472
473
bool FailedSelfUse);
473
474
474
- void handleSelfInitUse (DIMemoryUse &Use);
475
+ void handleSelfInitUse (unsigned UseID);
476
+
475
477
void updateInstructionForInitState (DIMemoryUse &Use);
476
478
477
479
@@ -764,15 +766,9 @@ void LifetimeChecker::doIt() {
764
766
handleStoreUse (i);
765
767
break ;
766
768
767
- case DIUseKind::IndirectIn: {
768
- bool IsSuperInitComplete, FailedSelfUse;
769
- // If the value is not definitively initialized, emit an error.
770
- if (!isInitializedAtUse (Use, &IsSuperInitComplete, &FailedSelfUse))
771
- handleLoadUseFailure (Use, IsSuperInitComplete, FailedSelfUse);
772
- break ;
773
- }
769
+ case DIUseKind::IndirectIn:
774
770
case DIUseKind::Load:
775
- handleLoadUse (i );
771
+ handleLoadUse (Use );
776
772
break ;
777
773
case DIUseKind::InOutArgument:
778
774
case DIUseKind::InOutSelfArgument:
@@ -782,7 +778,7 @@ void LifetimeChecker::doIt() {
782
778
handleEscapeUse (Use);
783
779
break ;
784
780
case DIUseKind::SelfInit:
785
- handleSelfInitUse (Use );
781
+ handleSelfInitUse (i );
786
782
break ;
787
783
case DIUseKind::LoadForTypeOfSelf:
788
784
handleLoadForTypeOfSelfUse (Use);
@@ -811,11 +807,15 @@ void LifetimeChecker::doIt() {
811
807
ControlVariable = handleConditionalInitAssign ();
812
808
if (!ConditionalDestroys.empty ())
813
809
handleConditionalDestroys (ControlVariable);
814
- }
815
810
816
- void LifetimeChecker::handleLoadUse (unsigned UseID) {
817
- DIMemoryUse &Use = Uses[UseID];
811
+ // handleStoreUse(), handleSelfInitUse() and handleConditionalInitAssign()
812
+ // postpone lowering of assignment instructions to avoid deleting
813
+ // instructions that still appear in the Uses list.
814
+ for (unsigned UseID : NeedsUpdateForInitState)
815
+ updateInstructionForInitState (Uses[UseID]);
816
+ }
818
817
818
+ void LifetimeChecker::handleLoadUse (const DIMemoryUse &Use) {
819
819
bool IsSuperInitComplete, FailedSelfUse;
820
820
// If the value is not definitively initialized, emit an error.
821
821
if (!isInitializedAtUse (Use, &IsSuperInitComplete, &FailedSelfUse))
@@ -1023,7 +1023,7 @@ void LifetimeChecker::handleStoreUse(unsigned UseID) {
1023
1023
1024
1024
// Otherwise, we have a definite init or assign. Make sure the instruction
1025
1025
// itself is tagged properly.
1026
- updateInstructionForInitState (Use );
1026
+ NeedsUpdateForInitState. push_back (UseID );
1027
1027
}
1028
1028
1029
1029
// / Check whether the instruction is an application.
@@ -1764,7 +1764,8 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
1764
1764
1765
1765
// / handleSelfInitUse - When processing a 'self' argument on a class, this is
1766
1766
// / a call to self.init or super.init.
1767
- void LifetimeChecker::handleSelfInitUse (DIMemoryUse &Use) {
1767
+ void LifetimeChecker::handleSelfInitUse (unsigned UseID) {
1768
+ auto &Use = Uses[UseID];
1768
1769
auto *Inst = Use.Inst ;
1769
1770
1770
1771
assert (TheMemory.isAnyInitSelf ());
@@ -1799,7 +1800,7 @@ void LifetimeChecker::handleSelfInitUse(DIMemoryUse &Use) {
1799
1800
1800
1801
// Lower Assign instructions if needed.
1801
1802
if (isa<AssignInst>(Use.Inst ))
1802
- updateInstructionForInitState (Use );
1803
+ NeedsUpdateForInitState. push_back (UseID );
1803
1804
} else {
1804
1805
// super.init also requires that all ivars are initialized before the
1805
1806
// superclass initializer runs.
@@ -1859,14 +1860,13 @@ void LifetimeChecker::updateInstructionForInitState(DIMemoryUse &Use) {
1859
1860
if (auto *AI = dyn_cast<AssignInst>(Inst)) {
1860
1861
// Remove this instruction from our data structures, since we will be
1861
1862
// removing it.
1862
- auto Kind = Use.Kind ;
1863
1863
Use.Inst = nullptr ;
1864
1864
NonLoadUses.erase (Inst);
1865
1865
1866
1866
PartialInitializationKind PartialInitKind;
1867
1867
1868
1868
if (TheMemory.isClassInitSelf () &&
1869
- Kind == DIUseKind::SelfInit) {
1869
+ Use. Kind == DIUseKind::SelfInit) {
1870
1870
assert (InitKind == IsInitialization);
1871
1871
PartialInitKind = PartialInitializationKind::IsReinitialization;
1872
1872
} else {
@@ -1875,27 +1875,8 @@ void LifetimeChecker::updateInstructionForInitState(DIMemoryUse &Use) {
1875
1875
: PartialInitializationKind::IsNotInitialization);
1876
1876
}
1877
1877
1878
- unsigned FirstElement = Use.FirstElement ;
1879
- unsigned NumElements = Use.NumElements ;
1880
-
1881
- SmallVector<SILInstruction*, 4 > InsertedInsts;
1882
- SILBuilderWithScope B (Inst, &InsertedInsts);
1878
+ SILBuilderWithScope B (Inst);
1883
1879
lowerAssignInstruction (B, AI, PartialInitKind);
1884
-
1885
- // If lowering of the assign introduced any new loads or stores, keep track
1886
- // of them.
1887
- for (auto I : InsertedInsts) {
1888
- if (isa<StoreInst>(I)) {
1889
- NonLoadUses[I] = Uses.size ();
1890
- Uses.push_back (DIMemoryUse (I, Kind, FirstElement, NumElements));
1891
- } else if (isa<LoadInst>(I)) {
1892
- // If we have a re-initialization, the value must be a class,
1893
- // and the load is just there so we can free the uninitialized
1894
- // object husk; it's not an actual use of 'self'.
1895
- if (PartialInitKind != PartialInitializationKind::IsReinitialization)
1896
- Uses.push_back (DIMemoryUse (I, Load, FirstElement, NumElements));
1897
- }
1898
- }
1899
1880
return ;
1900
1881
}
1901
1882
@@ -2193,6 +2174,12 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
2193
2174
2194
2175
// Ignore deleted uses.
2195
2176
if (Use.Inst == nullptr ) continue ;
2177
+
2178
+ // If this ambiguous store is only of trivial types, then we don't need to
2179
+ // do anything special. We don't even need keep the init bit for the
2180
+ // element precise.
2181
+ if (Use.onlyTouchesTrivialElements (TheMemory))
2182
+ continue ;
2196
2183
2197
2184
B.setInsertionPoint (Use.Inst );
2198
2185
@@ -2208,23 +2195,12 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
2208
2195
2209
2196
case DIUseKind::SelfInit:
2210
2197
case DIUseKind::Initialization:
2211
- // If this is an initialization of only trivial elements, then we don't
2212
- // need to update the bitvector.
2213
- if (Use.onlyTouchesTrivialElements (TheMemory))
2214
- continue ;
2215
-
2216
2198
APInt Bitmask = Use.getElementBitmask (NumMemoryElements);
2217
2199
SILBuilderWithScope SB (Use.Inst );
2218
2200
updateControlVariable (Loc, Bitmask, ControlVariableAddr, OrFn, SB);
2219
2201
continue ;
2220
2202
}
2221
2203
2222
- // If this ambiguous store is only of trivial types, then we don't need to
2223
- // do anything special. We don't even need keep the init bit for the
2224
- // element precise.
2225
- if (Use.onlyTouchesTrivialElements (TheMemory))
2226
- continue ;
2227
-
2228
2204
// If this is the interesting case, we need to generate a CFG diamond for
2229
2205
// each element touched, destroying any live elements so that the resulting
2230
2206
// store is always an initialize. This disambiguates the dynamic
@@ -2269,15 +2245,12 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
2269
2245
// Finally, now that we know the value is uninitialized on all paths, it is
2270
2246
// safe to do an unconditional initialization.
2271
2247
Use.Kind = DIUseKind::Initialization;
2272
-
2273
- // Now that the instruction has a concrete "init" form, update it to reflect
2274
- // that. Note that this can invalidate the Uses vector and delete
2275
- // the instruction.
2276
- updateInstructionForInitState (Use);
2277
-
2278
- // Revisit the instruction on the next pass through the loop, so that we
2279
- // emit a mask update as appropriate.
2280
- --i;
2248
+ NeedsUpdateForInitState.push_back (i);
2249
+
2250
+ // Update the control variable.
2251
+ APInt Bitmask = Use.getElementBitmask (NumMemoryElements);
2252
+ SILBuilderWithScope SB (Use.Inst );
2253
+ updateControlVariable (Loc, Bitmask, ControlVariableAddr, OrFn, SB);
2281
2254
}
2282
2255
2283
2256
// At each block that stores to self, mark the self value as having been
0 commit comments