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