Skip to content

Commit ba6763a

Browse files
committed
[di] Instead of accessing TheMemory.MemoryInst directly, use the helper getUninitializedValue().
This is going to let me change getUninitializedValue() to special case alloc_box so that we return the project_box (the address we want to analyze) rather than the mark_uninitialized (which is on the box).
1 parent 722d0bb commit ba6763a

File tree

3 files changed

+82
-73
lines changed

3 files changed

+82
-73
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

+46-49
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,33 @@ using namespace ownership;
2828
// Utility
2929
//===----------------------------------------------------------------------===//
3030

31-
static void gatherDestroysOfContainer(const MarkUninitializedInst *MUI,
32-
DIElementUseInfo &UseInfo) {
33-
// The MUI must be used on an alloc_box, alloc_stack, or global_addr. If we
34-
// have an alloc_stack or a global_addr, there is nothing further to do.
35-
if (isa<AllocStackInst>(MUI->getOperand()) ||
36-
isa<GlobalAddrInst>(MUI->getOperand()) ||
37-
isa<SILArgument>(MUI->getOperand()) ||
31+
static void gatherDestroysOfContainer(const DIMemoryObjectInfo &memoryInfo,
32+
DIElementUseInfo &useInfo) {
33+
auto *uninitMemory = memoryInfo.getUninitializedValue();
34+
35+
// The uninitMemory must be used on an alloc_box, alloc_stack, or global_addr.
36+
// If we have an alloc_stack or a global_addr, there is nothing further to do.
37+
if (isa<AllocStackInst>(uninitMemory->getOperand(0)) ||
38+
isa<GlobalAddrInst>(uninitMemory->getOperand(0)) ||
39+
isa<SILArgument>(uninitMemory->getOperand(0)) ||
3840
// FIXME: We only support pointer to address here to not break LLDB. It is
3941
// important that long term we get rid of this since this is a situation
4042
// where LLDB is breaking SILGen/DI invariants by not creating a new
4143
// independent stack location for the pointer to address.
42-
isa<PointerToAddressInst>(MUI->getOperand()))
44+
isa<PointerToAddressInst>(uninitMemory->getOperand(0))) {
4345
return;
46+
}
4447

45-
// Otherwise, we assume that we have a project_box. This is a hard cast to
46-
// ensure that we catch any new patterns emitted by SILGen and assert.
47-
auto *PBI = cast<ProjectBoxInst>(MUI->getOperand());
48-
auto *ABI = cast<AllocBoxInst>(PBI->getOperand());
49-
50-
// Treat destroys of the container as load+destroys of the original value.
48+
// Otherwise, we assume that we have an alloc_box. Treat destroys of the
49+
// alloc_box as load+destroys of the value stored in the box.
5150
//
5251
// TODO: This should really be tracked separately from other destroys so that
5352
// we distinguish the lifetime of the container from the value itself.
54-
for (auto *Op : ABI->getUses()) {
55-
SILInstruction *User = Op->getUser();
56-
if (isa<StrongReleaseInst>(User) || isa<DestroyValueInst>(User)) {
57-
UseInfo.trackDestroy(User);
58-
}
53+
assert(isa<MarkUninitializedInst>(uninitMemory));
54+
auto *pbi = cast<ProjectBoxInst>(uninitMemory->getOperand(0));
55+
auto *abi = cast<AllocBoxInst>(pbi->getOperand());
56+
for (auto *user : abi->getUsersOfType<DestroyValueInst>()) {
57+
useInfo.trackDestroy(user);
5958
}
6059
}
6160

@@ -215,7 +214,7 @@ SILType DIMemoryObjectInfo::getElementType(unsigned EltNo) const {
215214
SILValue DIMemoryObjectInfo::emitElementAddress(
216215
unsigned EltNo, SILLocation Loc, SILBuilder &B,
217216
llvm::SmallVectorImpl<std::pair<SILValue, SILValue>> &EndBorrowList) const {
218-
SILValue Ptr = getAddress();
217+
SILValue Ptr = getUninitializedValue();
219218
bool IsSelf = isNonDelegatingInit();
220219
auto &Module = MemoryInst->getModule();
221220

@@ -535,8 +534,7 @@ class ElementUseCollector {
535534
public:
536535
ElementUseCollector(const DIMemoryObjectInfo &TheMemory,
537536
DIElementUseInfo &UseInfo)
538-
: Module(TheMemory.MemoryInst->getModule()), TheMemory(TheMemory),
539-
UseInfo(UseInfo) {}
537+
: Module(TheMemory.getModule()), TheMemory(TheMemory), UseInfo(UseInfo) {}
540538

541539
/// This is the main entry point for the use walker. It collects uses from
542540
/// the address and the refcount result of the allocation.
@@ -553,8 +551,8 @@ class ElementUseCollector {
553551
return;
554552
}
555553

556-
collectUses(TheMemory.MemoryInst, 0);
557-
gatherDestroysOfContainer(TheMemory.MemoryInst, UseInfo);
554+
collectUses(TheMemory.getUninitializedValue(), 0);
555+
gatherDestroysOfContainer(TheMemory, UseInfo);
558556
}
559557

560558
void trackUse(DIMemoryUse Use) { UseInfo.trackUse(Use); }
@@ -564,8 +562,6 @@ class ElementUseCollector {
564562
/// Return the raw number of elements including the 'super.init' value.
565563
unsigned getNumMemoryElements() const { return TheMemory.getNumElements(); }
566564

567-
SILInstruction *getMemoryInst() const { return TheMemory.MemoryInst; }
568-
569565
private:
570566
void collectUses(SILValue Pointer, unsigned BaseEltNo);
571567
void collectClassSelfUses();
@@ -867,7 +863,7 @@ void ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
867863
// inout use.
868864
DIUseKind Kind;
869865
if (TheMemory.isStructInitSelf() &&
870-
getAccessedPointer(Pointer) == TheMemory.getAddress()) {
866+
getAccessedPointer(Pointer) == TheMemory.getUninitializedValue()) {
871867
Kind = DIUseKind::Escape;
872868
} else if (Apply.hasSelfArgument() &&
873869
Op == &Apply.getSelfArgumentOperand()) {
@@ -1089,8 +1085,7 @@ void ElementUseCollector::collectClassSelfUses() {
10891085
unsigned NumElements = 0;
10901086
for (auto *VD : NTD->getStoredProperties()) {
10911087
EltNumbering[VD] = NumElements;
1092-
auto expansionContext =
1093-
TypeExpansionContext(*TheMemory.MemoryInst->getFunction());
1088+
auto expansionContext = TypeExpansionContext(TheMemory.getFunction());
10941089
NumElements += getElementCountRec(
10951090
expansionContext, Module,
10961091
T.getFieldType(VD, Module, expansionContext), false);
@@ -1099,9 +1094,9 @@ void ElementUseCollector::collectClassSelfUses() {
10991094

11001095
// If we are looking at the init method for a root class, just walk the
11011096
// MUI use-def chain directly to find our uses.
1102-
auto *MemoryInst = TheMemory.MemoryInst;
1103-
if (MemoryInst->getKind() == MarkUninitializedInst::RootSelf) {
1104-
collectClassSelfUses(MemoryInst, TheMemory.getType(), EltNumbering);
1097+
if (TheMemory.isRootSelf()) {
1098+
collectClassSelfUses(TheMemory.getUninitializedValue(), TheMemory.getType(),
1099+
EltNumbering);
11051100
return;
11061101
}
11071102

@@ -1118,7 +1113,7 @@ void ElementUseCollector::collectClassSelfUses() {
11181113
// 4) Potential escapes after super.init, if self is closed over.
11191114
//
11201115
// Handle each of these in turn.
1121-
SmallVector<Operand *, 8> Uses(MemoryInst->getUses());
1116+
SmallVector<Operand *, 8> Uses(TheMemory.getUninitializedValue()->getUses());
11221117
while (!Uses.empty()) {
11231118
Operand *Op = Uses.pop_back_val();
11241119
SILInstruction *User = Op->getUser();
@@ -1129,7 +1124,7 @@ void ElementUseCollector::collectClassSelfUses() {
11291124
// The initial store of 'self' into the box at the start of the
11301125
// function. Ignore it.
11311126
if (auto *Arg = dyn_cast<SILArgument>(SI->getSrc())) {
1132-
if (Arg->getParent() == MemoryInst->getParent()) {
1127+
if (Arg->getParent() == TheMemory.getParentBlock()) {
11331128
StoresOfArgumentToSelf++;
11341129
continue;
11351130
}
@@ -1144,7 +1139,7 @@ void ElementUseCollector::collectClassSelfUses() {
11441139
src = conversion->getConverted();
11451140

11461141
if (auto *LI = dyn_cast<LoadInst>(src))
1147-
if (LI->getOperand() == MemoryInst)
1142+
if (LI->getOperand() == TheMemory.getUninitializedValue())
11481143
continue;
11491144

11501145
// Any other store needs to be recorded.
@@ -1583,7 +1578,7 @@ class ClassInitElementUseCollector {
15831578

15841579
// *NOTE* Even though this takes a SILInstruction it actually only accepts
15851580
// load_borrow and load instructions. This is enforced via an assert.
1586-
void collectClassInitSelfLoadUses(MarkUninitializedInst *MUI,
1581+
void collectClassInitSelfLoadUses(SingleValueInstruction *MUI,
15871582
SingleValueInstruction *LI);
15881583
};
15891584

@@ -1596,21 +1591,21 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() {
15961591
// all. Just treat all members of self as uses of the single
15971592
// non-field-sensitive value.
15981593
assert(TheMemory.getNumElements() == 1 && "delegating inits only have 1 bit");
1599-
auto *MUI = TheMemory.MemoryInst;
1594+
auto *uninitMemory = TheMemory.getUninitializedValue();
16001595

16011596
// The number of stores of the initial 'self' argument into the self box
16021597
// that we saw.
16031598
unsigned StoresOfArgumentToSelf = 0;
16041599

1605-
// We walk the use chains of the self MUI to find any accesses to it. The
1606-
// possible uses are:
1600+
// We walk the use chains of the self uninitMemory to find any accesses to it.
1601+
// The possible uses are:
16071602
// 1) The initialization store.
16081603
// 2) Loads of the box, which have uses of self hanging off of them.
16091604
// 3) An assign to the box, which happens at super.init.
16101605
// 4) Potential escapes after super.init, if self is closed over.
16111606
// Handle each of these in turn.
16121607
//
1613-
SmallVector<Operand *, 8> Uses(MUI->getUses());
1608+
SmallVector<Operand *, 8> Uses(uninitMemory->getUses());
16141609
while (!Uses.empty()) {
16151610
Operand *Op = Uses.pop_back_val();
16161611
SILInstruction *User = Op->getUser();
@@ -1634,7 +1629,7 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() {
16341629
// A store of 'self' into the box at the start of the
16351630
// function. Ignore it.
16361631
if (auto *Arg = dyn_cast<SILArgument>(SI->getSrc())) {
1637-
if (Arg->getParent() == MUI->getParent()) {
1632+
if (Arg->getParent() == uninitMemory->getParent()) {
16381633
StoresOfArgumentToSelf++;
16391634
continue;
16401635
}
@@ -1649,7 +1644,7 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() {
16491644
src = conversion->getConverted();
16501645

16511646
if (auto *LI = dyn_cast<LoadInst>(src))
1652-
if (LI->getOperand() == MUI)
1647+
if (LI->getOperand() == uninitMemory)
16531648
continue;
16541649

16551650
// Any other store needs to be recorded.
@@ -1699,7 +1694,8 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() {
16991694

17001695
// Loads of the box produce self, so collect uses from them.
17011696
if (isa<LoadInst>(User) || isa<LoadBorrowInst>(User)) {
1702-
collectClassInitSelfLoadUses(MUI, cast<SingleValueInstruction>(User));
1697+
collectClassInitSelfLoadUses(uninitMemory,
1698+
cast<SingleValueInstruction>(User));
17031699
continue;
17041700
}
17051701

@@ -1718,12 +1714,12 @@ void ClassInitElementUseCollector::collectClassInitSelfUses() {
17181714
"The 'self' argument should have been stored into the box exactly once");
17191715

17201716
// Gather the uses of the
1721-
gatherDestroysOfContainer(MUI, UseInfo);
1717+
gatherDestroysOfContainer(TheMemory, UseInfo);
17221718
}
17231719

1724-
void ClassInitElementUseCollector::
1725-
collectClassInitSelfLoadUses(MarkUninitializedInst *MUI,
1726-
SingleValueInstruction *LI) {
1720+
void ClassInitElementUseCollector::collectClassInitSelfLoadUses(
1721+
SingleValueInstruction *MUI, SingleValueInstruction *LI) {
1722+
assert(isa<ProjectBoxInst>(MUI) || isa<MarkUninitializedInst>(MUI));
17271723
assert(isa<LoadBorrowInst>(LI) || isa<LoadInst>(LI));
17281724

17291725
// If we have a load, then this is a use of the box. Look at the uses of
@@ -1805,7 +1801,7 @@ collectClassInitSelfLoadUses(MarkUninitializedInst *MUI,
18051801
//===----------------------------------------------------------------------===//
18061802

18071803
static bool shouldPerformClassInitSelf(const DIMemoryObjectInfo &MemoryInfo) {
1808-
if (MemoryInfo.MemoryInst->isDelegatingSelfAllocated())
1804+
if (MemoryInfo.isDelegatingSelfAllocated())
18091805
return true;
18101806

18111807
return MemoryInfo.isNonDelegatingInit() &&
@@ -1831,7 +1827,8 @@ void swift::ownership::collectDIElementUsesFrom(
18311827
// non-field-sensitive value.
18321828
assert(MemoryInfo.getNumElements() == 1 &&
18331829
"delegating inits only have 1 bit");
1834-
collectDelegatingInitUses(MemoryInfo, UseInfo, MemoryInfo.MemoryInst);
1830+
collectDelegatingInitUses(MemoryInfo, UseInfo,
1831+
MemoryInfo.getUninitializedValue());
18351832
return;
18361833
}
18371834

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h

+17-4
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,9 @@ struct DIElementUseInfo;
5252
/// Derived classes have an additional field at the end that models whether or
5353
/// not super.init() has been called or not.
5454
class DIMemoryObjectInfo {
55-
public:
5655
/// The uninitialized memory that we are analyzing.
5756
MarkUninitializedInst *MemoryInst;
5857

59-
private:
6058
/// This is the base type of the memory allocation.
6159
SILType MemorySILType;
6260

@@ -66,7 +64,6 @@ class DIMemoryObjectInfo {
6664
/// initialized).
6765
unsigned NumElements;
6866

69-
private:
7067
/// True if the memory object being analyzed represents a 'let', which is
7168
/// initialize-only (reassignments are not allowed).
7269
bool IsLet = false;
@@ -80,6 +77,8 @@ class DIMemoryObjectInfo {
8077

8178
SILLocation getLoc() const { return MemoryInst->getLoc(); }
8279
SILFunction &getFunction() const { return *MemoryInst->getFunction(); }
80+
SILModule &getModule() const { return MemoryInst->getModule(); }
81+
SILBasicBlock *getParentBlock() const { return MemoryInst->getParent(); }
8382

8483
/// Return the first instruction of the function containing the memory object.
8584
SILInstruction *getFunctionEntryPoint() const;
@@ -94,7 +93,13 @@ class DIMemoryObjectInfo {
9493
/// be non-empty.
9594
bool hasDummyElement() const { return HasDummyElement; }
9695

97-
SingleValueInstruction *getAddress() const { return MemoryInst; }
96+
/// Return the actual 'uninitialized' memory. In the case of alloc_ref,
97+
/// alloc_stack, this always just returns the actual mark_uninitialized
98+
/// instruction. For alloc_box though it returns the project_box associated
99+
/// with the memory info.
100+
SingleValueInstruction *getUninitializedValue() const {
101+
return MemoryInst;
102+
}
98103

99104
/// Return the number of elements, without the extra "super.init" tracker in
100105
/// initializers of derived classes.
@@ -194,6 +199,14 @@ class DIMemoryObjectInfo {
194199
return false;
195200
}
196201

202+
bool isRootSelf() const {
203+
return MemoryInst->getKind() == MarkUninitializedInst::RootSelf;
204+
}
205+
206+
bool isDelegatingSelfAllocated() const {
207+
return MemoryInst->isDelegatingSelfAllocated();
208+
}
209+
197210
/// Given an element number (in the flattened sense) return a pointer to a
198211
/// leaf element of the specified number.
199212
SILValue

0 commit comments

Comments
 (0)