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