@@ -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;
@@ -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
@@ -777,7 +779,7 @@ void LifetimeChecker::doIt() {
777
779
handleEscapeUse (Use);
778
780
break ;
779
781
case DIUseKind::SelfInit:
780
- handleSelfInitUse (Use );
782
+ handleSelfInitUse (i );
781
783
break ;
782
784
case DIUseKind::LoadForTypeOfSelf:
783
785
handleLoadForTypeOfSelfUse (Use);
@@ -806,6 +808,12 @@ void LifetimeChecker::doIt() {
806
808
ControlVariable = handleConditionalInitAssign ();
807
809
if (!ConditionalDestroys.empty ())
808
810
handleConditionalDestroys (ControlVariable);
811
+
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]);
809
817
}
810
818
811
819
void LifetimeChecker::handleLoadUse (const DIMemoryUse &Use) {
@@ -1016,7 +1024,7 @@ void LifetimeChecker::handleStoreUse(unsigned UseID) {
1016
1024
1017
1025
// Otherwise, we have a definite init or assign. Make sure the instruction
1018
1026
// itself is tagged properly.
1019
- updateInstructionForInitState (Use );
1027
+ NeedsUpdateForInitState. push_back (UseID );
1020
1028
}
1021
1029
1022
1030
// / Check whether the instruction is an application.
@@ -1757,7 +1765,8 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
1757
1765
1758
1766
// / handleSelfInitUse - When processing a 'self' argument on a class, this is
1759
1767
// / a call to self.init or super.init.
1760
- void LifetimeChecker::handleSelfInitUse (DIMemoryUse &Use) {
1768
+ void LifetimeChecker::handleSelfInitUse (unsigned UseID) {
1769
+ auto &Use = Uses[UseID];
1761
1770
auto *Inst = Use.Inst ;
1762
1771
1763
1772
assert (TheMemory.isAnyInitSelf ());
@@ -1792,7 +1801,7 @@ void LifetimeChecker::handleSelfInitUse(DIMemoryUse &Use) {
1792
1801
1793
1802
// Lower Assign instructions if needed.
1794
1803
if (isa<AssignInst>(Use.Inst ))
1795
- updateInstructionForInitState (Use );
1804
+ NeedsUpdateForInitState. push_back (UseID );
1796
1805
} else {
1797
1806
// super.init also requires that all ivars are initialized before the
1798
1807
// superclass initializer runs.
@@ -1852,14 +1861,13 @@ void LifetimeChecker::updateInstructionForInitState(DIMemoryUse &Use) {
1852
1861
if (auto *AI = dyn_cast<AssignInst>(Inst)) {
1853
1862
// Remove this instruction from our data structures, since we will be
1854
1863
// removing it.
1855
- auto Kind = Use.Kind ;
1856
1864
Use.Inst = nullptr ;
1857
1865
NonLoadUses.erase (Inst);
1858
1866
1859
1867
PartialInitializationKind PartialInitKind;
1860
1868
1861
1869
if (TheMemory.isClassInitSelf () &&
1862
- Kind == DIUseKind::SelfInit) {
1870
+ Use. Kind == DIUseKind::SelfInit) {
1863
1871
assert (InitKind == IsInitialization);
1864
1872
PartialInitKind = PartialInitializationKind::IsReinitialization;
1865
1873
} else {
@@ -1868,27 +1876,8 @@ void LifetimeChecker::updateInstructionForInitState(DIMemoryUse &Use) {
1868
1876
: PartialInitializationKind::IsNotInitialization);
1869
1877
}
1870
1878
1871
- unsigned FirstElement = Use.FirstElement ;
1872
- unsigned NumElements = Use.NumElements ;
1873
-
1874
- SmallVector<SILInstruction*, 4 > InsertedInsts;
1875
- SILBuilderWithScope B (Inst, &InsertedInsts);
1879
+ SILBuilderWithScope B (Inst);
1876
1880
lowerAssignInstruction (B, AI, PartialInitKind);
1877
-
1878
- // If lowering of the assign introduced any new loads or stores, keep track
1879
- // of them.
1880
- for (auto I : InsertedInsts) {
1881
- if (isa<StoreInst>(I)) {
1882
- NonLoadUses[I] = Uses.size ();
1883
- Uses.push_back (DIMemoryUse (I, Kind, FirstElement, NumElements));
1884
- } else if (isa<LoadInst>(I)) {
1885
- // If we have a re-initialization, the value must be a class,
1886
- // and the load is just there so we can free the uninitialized
1887
- // object husk; it's not an actual use of 'self'.
1888
- if (PartialInitKind != PartialInitializationKind::IsReinitialization)
1889
- Uses.push_back (DIMemoryUse (I, Load, FirstElement, NumElements));
1890
- }
1891
- }
1892
1881
return ;
1893
1882
}
1894
1883
@@ -2257,15 +2246,12 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
2257
2246
// Finally, now that we know the value is uninitialized on all paths, it is
2258
2247
// safe to do an unconditional initialization.
2259
2248
Use.Kind = DIUseKind::Initialization;
2260
-
2261
- // Now that the instruction has a concrete "init" form, update it to reflect
2262
- // that. Note that this can invalidate the Uses vector and delete
2263
- // the instruction.
2264
- updateInstructionForInitState (Use);
2265
-
2266
- // Revisit the instruction on the next pass through the loop, so that we
2267
- // emit a mask update as appropriate.
2268
- --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);
2269
2255
}
2270
2256
2271
2257
// At each block that stores to self, mark the self value as having been
0 commit comments