Skip to content

Commit 160742a

Browse files
authored
Merge pull request #16782 from gottesmm/pr-8cb08737bbc02f7bd7b79cd80cd7d3ccde893680
Two small cleanups for DI since I am in the area.
2 parents b3bc06e + 1bc3190 commit 160742a

File tree

1 file changed

+87
-86
lines changed

1 file changed

+87
-86
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollectorOwnership.cpp

Lines changed: 87 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,24 +1459,79 @@ void ElementUseCollector::collectClassSelfUses(
14591459
}
14601460

14611461
//===----------------------------------------------------------------------===//
1462-
// DelegatingInitElementUseCollector
1462+
// DelegatingValueTypeInitUseCollector
1463+
//===----------------------------------------------------------------------===//
1464+
1465+
static void
1466+
collectValueTypeDelegatingInitUses(const DIMemoryObjectInfo &TheMemory,
1467+
DIElementUseInfo &UseInfo,
1468+
SingleValueInstruction *I) {
1469+
for (auto *Op : I->getUses()) {
1470+
auto *User = Op->getUser();
1471+
1472+
// destroy_addr is a release of the entire value. This can result from an
1473+
// early release due to a conditional initializer.
1474+
if (isa<DestroyAddrInst>(User)) {
1475+
UseInfo.trackDestroy(User);
1476+
continue;
1477+
}
1478+
1479+
// For delegating initializers, we only track calls to self.init with
1480+
// specialized code. All other uses are modeled as escapes.
1481+
//
1482+
// *NOTE* This intentionally ignores all stores, which (if they got emitted
1483+
// as copyaddr or assigns) will eventually get rewritten as assignments (not
1484+
// initializations), which is the right thing to do.
1485+
DIUseKind Kind = DIUseKind::Escape;
1486+
1487+
// Stores *to* the allocation are writes. If the value being stored is a
1488+
// call to self.init()... then we have a self.init call.
1489+
if (auto *AI = dyn_cast<AssignInst>(User)) {
1490+
if (AI->getDest() == I) {
1491+
UseInfo.trackStoreToSelf(AI);
1492+
Kind = DIUseKind::InitOrAssign;
1493+
}
1494+
}
1495+
1496+
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
1497+
if (CAI->getDest() == I) {
1498+
UseInfo.trackStoreToSelf(CAI);
1499+
Kind = DIUseKind::InitOrAssign;
1500+
}
1501+
}
1502+
1503+
// Look through begin_access
1504+
if (auto *BAI = dyn_cast<BeginAccessInst>(User)) {
1505+
collectValueTypeDelegatingInitUses(TheMemory, UseInfo, BAI);
1506+
continue;
1507+
}
1508+
1509+
// Ignore end_access
1510+
if (isa<EndAccessInst>(User))
1511+
continue;
1512+
1513+
// We can safely handle anything else as an escape. They should all happen
1514+
// after self.init is invoked.
1515+
UseInfo.trackUse(DIMemoryUse(User, Kind, 0, 1));
1516+
}
1517+
}
1518+
1519+
//===----------------------------------------------------------------------===//
1520+
// DelegatingClassInitElementUseCollector
14631521
//===----------------------------------------------------------------------===//
14641522

14651523
namespace {
14661524

1467-
class DelegatingInitElementUseCollector {
1525+
class DelegatingClassInitElementUseCollector {
14681526
const DIMemoryObjectInfo &TheMemory;
14691527
DIElementUseInfo &UseInfo;
14701528

1471-
void collectValueTypeInitSelfUses(SingleValueInstruction *I);
1472-
14731529
public:
1474-
DelegatingInitElementUseCollector(const DIMemoryObjectInfo &TheMemory,
1475-
DIElementUseInfo &UseInfo)
1530+
DelegatingClassInitElementUseCollector(const DIMemoryObjectInfo &TheMemory,
1531+
DIElementUseInfo &UseInfo)
14761532
: TheMemory(TheMemory), UseInfo(UseInfo) {}
14771533

14781534
void collectClassInitSelfUses();
1479-
void collectValueTypeInitSelfUses();
14801535

14811536
// *NOTE* Even though this takes a SILInstruction it actually only accepts
14821537
// load_borrow and load instructions. This is enforced via an assert.
@@ -1488,7 +1543,7 @@ class DelegatingInitElementUseCollector {
14881543

14891544
/// collectDelegatingClassInitSelfUses - Collect uses of the self argument in a
14901545
/// delegating-constructor-for-a-class case.
1491-
void DelegatingInitElementUseCollector::collectClassInitSelfUses() {
1546+
void DelegatingClassInitElementUseCollector::collectClassInitSelfUses() {
14921547
// When we're analyzing a delegating constructor, we aren't field sensitive at
14931548
// all. Just treat all members of self as uses of the single
14941549
// non-field-sensitive value.
@@ -1631,70 +1686,9 @@ void DelegatingInitElementUseCollector::collectClassInitSelfUses() {
16311686
}
16321687
}
16331688

1634-
void DelegatingInitElementUseCollector::collectValueTypeInitSelfUses(
1635-
SingleValueInstruction *I) {
1636-
for (auto Op : I->getUses()) {
1637-
auto *User = Op->getUser();
1638-
1639-
// destroy_addr is a release of the entire value. This can result from an
1640-
// early release due to a conditional initializer.
1641-
if (isa<DestroyAddrInst>(User)) {
1642-
UseInfo.trackDestroy(User);
1643-
continue;
1644-
}
1645-
1646-
// For delegating initializers, we only track calls to self.init with
1647-
// specialized code. All other uses are modeled as escapes.
1648-
//
1649-
// *NOTE* This intentionally ignores all stores, which (if they got emitted
1650-
// as copyaddr or assigns) will eventually get rewritten as assignments (not
1651-
// initializations), which is the right thing to do.
1652-
DIUseKind Kind = DIUseKind::Escape;
1653-
1654-
// Stores *to* the allocation are writes. If the value being stored is a
1655-
// call to self.init()... then we have a self.init call.
1656-
if (auto *AI = dyn_cast<AssignInst>(User)) {
1657-
if (AI->getDest() == I) {
1658-
UseInfo.trackStoreToSelf(AI);
1659-
Kind = DIUseKind::InitOrAssign;
1660-
}
1661-
}
1662-
1663-
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
1664-
if (CAI->getDest() == I) {
1665-
UseInfo.trackStoreToSelf(CAI);
1666-
Kind = DIUseKind::InitOrAssign;
1667-
}
1668-
}
1669-
1670-
// Look through begin_access
1671-
if (auto *BAI = dyn_cast<BeginAccessInst>(User)) {
1672-
collectValueTypeInitSelfUses(BAI);
1673-
continue;
1674-
}
1675-
1676-
// Ignore end_access
1677-
if (isa<EndAccessInst>(User))
1678-
continue;
1679-
1680-
// We can safely handle anything else as an escape. They should all happen
1681-
// after self.init is invoked.
1682-
UseInfo.trackUse(DIMemoryUse(User, Kind, 0, 1));
1683-
}
1684-
}
1685-
1686-
void DelegatingInitElementUseCollector::collectValueTypeInitSelfUses() {
1687-
// When we're analyzing a delegating constructor, we aren't field sensitive at
1688-
// all. Just treat all members of self as uses of the single
1689-
// non-field-sensitive value.
1690-
assert(TheMemory.NumElements == 1 && "delegating inits only have 1 bit");
1691-
1692-
auto *MUI = cast<MarkUninitializedInst>(TheMemory.MemoryInst);
1693-
collectValueTypeInitSelfUses(MUI);
1694-
}
1695-
1696-
void DelegatingInitElementUseCollector::collectDelegatingClassInitSelfLoadUses(
1697-
MarkUninitializedInst *MUI, SingleValueInstruction *LI) {
1689+
void DelegatingClassInitElementUseCollector::
1690+
collectDelegatingClassInitSelfLoadUses(MarkUninitializedInst *MUI,
1691+
SingleValueInstruction *LI) {
16981692
assert(isa<LoadBorrowInst>(LI) || isa<LoadInst>(LI));
16991693

17001694
// If we have a load, then this is a use of the box. Look at the uses of
@@ -1775,31 +1769,38 @@ void DelegatingInitElementUseCollector::collectDelegatingClassInitSelfLoadUses(
17751769
// Top Level Entrypoint
17761770
//===----------------------------------------------------------------------===//
17771771

1772+
static bool shouldPerformClassInitSelf(const DIMemoryObjectInfo &MemoryInfo) {
1773+
if (MemoryInfo.isDelegatingInit()) {
1774+
assert(MemoryInfo.isClassInitSelf());
1775+
return true;
1776+
}
1777+
1778+
return MemoryInfo.isNonDelegatingInit() &&
1779+
MemoryInfo.getType()->getClassOrBoundGenericClass() != nullptr &&
1780+
MemoryInfo.isDerivedClassSelfOnly();
1781+
}
1782+
17781783
/// collectDIElementUsesFrom - Analyze all uses of the specified allocation
17791784
/// instruction (alloc_box, alloc_stack or mark_uninitialized), classifying them
17801785
/// and storing the information found into the Uses and Releases lists.
17811786
void swift::ownership::collectDIElementUsesFrom(
17821787
const DIMemoryObjectInfo &MemoryInfo, DIElementUseInfo &UseInfo,
17831788
bool isDIFinished, bool TreatAddressToPointerAsInout) {
1784-
// If we have a delegating init, use the delegating init element use
1785-
// collector.
1786-
if (MemoryInfo.isDelegatingInit()) {
1787-
DelegatingInitElementUseCollector UseCollector(MemoryInfo, UseInfo);
1788-
if (MemoryInfo.isClassInitSelf()) {
1789-
UseCollector.collectClassInitSelfUses();
1790-
} else {
1791-
UseCollector.collectValueTypeInitSelfUses();
1792-
}
17931789

1790+
if (MemoryInfo.isDelegatingInit() && !MemoryInfo.isClassInitSelf()) {
1791+
// When we're analyzing a delegating constructor, we aren't field sensitive
1792+
// at all. Just treat all members of self as uses of the single
1793+
// non-field-sensitive value.
1794+
assert(MemoryInfo.NumElements == 1 && "delegating inits only have 1 bit");
1795+
auto *MUI = cast<MarkUninitializedInst>(MemoryInfo.MemoryInst);
1796+
collectValueTypeDelegatingInitUses(MemoryInfo, UseInfo, MUI);
17941797
MemoryInfo.collectRetainCountInfo(UseInfo);
17951798
return;
17961799
}
17971800

1798-
if (MemoryInfo.isNonDelegatingInit() &&
1799-
MemoryInfo.getType()->getClassOrBoundGenericClass() != nullptr &&
1800-
MemoryInfo.isDerivedClassSelfOnly()) {
1801-
DelegatingInitElementUseCollector(MemoryInfo, UseInfo)
1802-
.collectClassInitSelfUses();
1801+
if (shouldPerformClassInitSelf(MemoryInfo)) {
1802+
DelegatingClassInitElementUseCollector UseCollector(MemoryInfo, UseInfo);
1803+
UseCollector.collectClassInitSelfUses();
18031804
MemoryInfo.collectRetainCountInfo(UseInfo);
18041805
return;
18051806
}

0 commit comments

Comments
 (0)