@@ -565,6 +565,13 @@ struct AddressLoweringState {
565
565
// / @returns nullable value
566
566
SILValue getEarliestStoragePoint (SILValue userValue, bool allowsInit) const ;
567
567
568
+ // / Finds and caches the latest opening instruction of the type of the value
569
+ // / in \p pair.
570
+ // /
571
+ // / @returns nullable instruction
572
+ SILInstruction *
573
+ getLatestOpeningInst (const ValueStorageMap::ValueStoragePair *) const ;
574
+
568
575
// / The latest instruction which opens an archetype involved in the indicated
569
576
// / type.
570
577
// /
@@ -1256,6 +1263,15 @@ void OpaqueStorageAllocation::allocateValue(SILValue value) {
1256
1263
createStackAllocationStorage (value);
1257
1264
}
1258
1265
1266
+ SILInstruction *AddressLoweringState::getLatestOpeningInst (
1267
+ const ValueStorageMap::ValueStoragePair *pair) const {
1268
+ if (!pair->storage .latestOpeningInst .has_value ()) {
1269
+ auto *loi = getLatestOpeningInst (pair->value ->getType ());
1270
+ pair->storage .latestOpeningInst = {loi};
1271
+ }
1272
+ return pair->storage .latestOpeningInst .value ();
1273
+ }
1274
+
1259
1275
SILValue AddressLoweringState::getEarliestStoragePoint (SILValue userValue,
1260
1276
bool allowsInit) const {
1261
1277
for (auto *pair : valueStorageMap.getProjections (userValue)) {
@@ -1265,6 +1281,9 @@ SILValue AddressLoweringState::getEarliestStoragePoint(SILValue userValue,
1265
1281
// not allowed. The projection will be inserted here.
1266
1282
return pair->value ;
1267
1283
}
1284
+ if (auto *loi = getLatestOpeningInst (pair)) {
1285
+ return cast<SingleValueInstruction>(loi);
1286
+ }
1268
1287
assert (!(storage.isProjection () && storage.storageAddress ));
1269
1288
// Reached the bottom of the projection tower. There must be storage.
1270
1289
if (!storage.isProjection ()) {
@@ -1781,6 +1800,7 @@ AddressLoweringState::getProjectionInsertionPoint(SILValue userValue) const {
1781
1800
if (!valueStorageMap.getStorage (userValue).isProjection ()) {
1782
1801
return userValue->getDefiningInsertionPoint ();
1783
1802
}
1803
+ SILInstruction *obstruction = nullptr ;
1784
1804
SILInstruction *retval = nullptr ;
1785
1805
for (auto *pair : valueStorageMap.getProjections (userValue)) {
1786
1806
auto const &storage = pair->storage ;
@@ -1789,8 +1809,18 @@ AddressLoweringState::getProjectionInsertionPoint(SILValue userValue) const {
1789
1809
retval = storage.storageAddress ->getNextInstruction ();
1790
1810
break ;
1791
1811
}
1812
+ if (!obstruction) {
1813
+ // It's only necessary to consider the obstruction to the earliest
1814
+ // projection because obstructions to any others must dominate it.
1815
+ if (auto *loi = getLatestOpeningInst (pair))
1816
+ obstruction = loi->getNextInstruction ();
1817
+ }
1792
1818
}
1793
1819
assert (retval);
1820
+ if (obstruction) {
1821
+ if (domInfo->dominates (retval, obstruction))
1822
+ retval = obstruction;
1823
+ }
1794
1824
return retval;
1795
1825
}
1796
1826
0 commit comments