Skip to content

Commit 5da00da

Browse files
authored
Merge pull request #21645 from gottesmm/pr-925cb5305b32ae67b973b608cd43dfb08b84ccd7
[pmo] Eliminate dead flat namespace tuple numbering from PMOMemoryUseCollector.
2 parents 0295e04 + 7b7ccdc commit 5da00da

File tree

3 files changed

+56
-213
lines changed

3 files changed

+56
-213
lines changed

lib/SILOptimizer/Mandatory/PMOMemoryUseCollector.cpp

Lines changed: 53 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,9 @@
2323
using namespace swift;
2424

2525
//===----------------------------------------------------------------------===//
26-
// PMOMemoryObjectInfo Implementation
26+
// PMOMemoryObjectInfo Implementation
2727
//===----------------------------------------------------------------------===//
2828

29-
static unsigned getElementCountRec(SILModule &Module, SILType T) {
30-
// If this is a tuple, it is always recursively flattened.
31-
if (CanTupleType TT = T.getAs<TupleType>()) {
32-
unsigned NumElements = 0;
33-
for (unsigned i = 0, e = TT->getNumElements(); i < e; i++)
34-
NumElements += getElementCountRec(Module, T.getTupleElementType(i));
35-
return NumElements;
36-
}
37-
38-
// Otherwise, it is a single element.
39-
return 1;
40-
}
41-
4229
PMOMemoryObjectInfo::PMOMemoryObjectInfo(AllocationInst *allocation)
4330
: MemoryInst(allocation) {
4431
auto &module = MemoryInst->getModule();
@@ -51,90 +38,12 @@ PMOMemoryObjectInfo::PMOMemoryObjectInfo(AllocationInst *allocation)
5138
} else {
5239
MemorySILType = cast<AllocStackInst>(MemoryInst)->getElementType();
5340
}
54-
55-
// Break down the initializer.
56-
NumElements = getElementCountRec(module, MemorySILType);
5741
}
5842

5943
SILInstruction *PMOMemoryObjectInfo::getFunctionEntryPoint() const {
6044
return &*getFunction().begin()->begin();
6145
}
6246

63-
/// Given a symbolic element number, return the type of the element.
64-
static SILType getElementTypeRec(SILModule &Module, SILType T, unsigned EltNo) {
65-
// If this is a tuple type, walk into it.
66-
if (CanTupleType TT = T.getAs<TupleType>()) {
67-
for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) {
68-
auto FieldType = T.getTupleElementType(i);
69-
unsigned NumFieldElements = getElementCountRec(Module, FieldType);
70-
if (EltNo < NumFieldElements)
71-
return getElementTypeRec(Module, FieldType, EltNo);
72-
EltNo -= NumFieldElements;
73-
}
74-
// This can only happen if we look at a symbolic element number of an empty
75-
// tuple.
76-
llvm::report_fatal_error("invalid element number");
77-
}
78-
79-
// Otherwise, it is a leaf element.
80-
assert(EltNo == 0);
81-
return T;
82-
}
83-
84-
/// getElementTypeRec - Return the swift type of the specified element.
85-
SILType PMOMemoryObjectInfo::getElementType(unsigned EltNo) const {
86-
auto &Module = MemoryInst->getModule();
87-
return getElementTypeRec(Module, MemorySILType, EltNo);
88-
}
89-
90-
/// Push the symbolic path name to the specified element number onto the
91-
/// specified std::string.
92-
static void getPathStringToElementRec(SILModule &Module, SILType T,
93-
unsigned EltNo, std::string &Result) {
94-
if (CanTupleType TT = T.getAs<TupleType>()) {
95-
unsigned FieldNo = 0;
96-
for (unsigned i = 0, e = TT->getNumElements(); i < e; i++) {
97-
auto Field = TT->getElement(i);
98-
SILType FieldTy = T.getTupleElementType(i);
99-
unsigned NumFieldElements = getElementCountRec(Module, FieldTy);
100-
101-
if (EltNo < NumFieldElements) {
102-
Result += '.';
103-
if (Field.hasName())
104-
Result += Field.getName().str();
105-
else
106-
Result += llvm::utostr(FieldNo);
107-
return getPathStringToElementRec(Module, FieldTy, EltNo, Result);
108-
}
109-
110-
EltNo -= NumFieldElements;
111-
112-
++FieldNo;
113-
}
114-
llvm_unreachable("Element number is out of range for this type!");
115-
}
116-
117-
// Otherwise, there are no subelements.
118-
assert(EltNo == 0 && "Element count problem");
119-
}
120-
121-
ValueDecl *
122-
PMOMemoryObjectInfo::getPathStringToElement(unsigned Element,
123-
std::string &Result) const {
124-
auto &Module = MemoryInst->getModule();
125-
126-
if (auto *VD = dyn_cast_or_null<ValueDecl>(getLoc().getAsASTNode<Decl>()))
127-
Result = VD->getBaseName().userFacingName();
128-
else
129-
Result = "<unknown>";
130-
131-
// Get the path through a tuple, if relevant.
132-
getPathStringToElementRec(Module, MemorySILType, Element, Result);
133-
134-
// Otherwise, we can't.
135-
return nullptr;
136-
}
137-
13847
//===----------------------------------------------------------------------===//
13948
// Scalarization Logic
14049
//===----------------------------------------------------------------------===//
@@ -207,14 +116,11 @@ class ElementUseCollector {
207116
LLVM_NODISCARD bool collectFrom();
208117

209118
private:
210-
LLVM_NODISCARD bool collectUses(SILValue Pointer, unsigned BaseEltNo);
119+
LLVM_NODISCARD bool collectUses(SILValue Pointer);
211120
LLVM_NODISCARD bool collectContainerUses(AllocBoxInst *ABI);
212-
void addElementUses(unsigned BaseEltNo, SILType UseTy, SILInstruction *User,
213-
PMOUseKind Kind);
214-
LLVM_NODISCARD bool collectTupleElementUses(TupleElementAddrInst *TEAI,
215-
unsigned BaseEltNo);
216-
LLVM_NODISCARD bool collectStructElementUses(StructElementAddrInst *SEAI,
217-
unsigned BaseEltNo);
121+
void addElementUses(SILInstruction *User, PMOUseKind Kind);
122+
LLVM_NODISCARD bool collectTupleElementUses(TupleElementAddrInst *TEAI);
123+
LLVM_NODISCARD bool collectStructElementUses(StructElementAddrInst *SEAI);
218124
};
219125
} // end anonymous namespace
220126

@@ -224,7 +130,7 @@ bool ElementUseCollector::collectFrom() {
224130
if (auto *ABI = TheMemory.getContainer()) {
225131
shouldOptimize = collectContainerUses(ABI);
226132
} else {
227-
shouldOptimize = collectUses(TheMemory.getAddress(), 0);
133+
shouldOptimize = collectUses(TheMemory.getAddress());
228134
}
229135

230136
if (!shouldOptimize)
@@ -247,51 +153,28 @@ bool ElementUseCollector::collectFrom() {
247153
/// acts on all of the aggregate elements in that value. For example, a load
248154
/// of $*(Int,Int) is a use of both Int elements of the tuple. This is a helper
249155
/// to keep the Uses data structure up to date for aggregate uses.
250-
void ElementUseCollector::addElementUses(unsigned BaseEltNo, SILType UseTy,
251-
SILInstruction *User,
156+
void ElementUseCollector::addElementUses(SILInstruction *User,
252157
PMOUseKind Kind) {
253-
// If we're in a subelement of a struct or enum, just mark the struct, not
254-
// things that come after it in a parent tuple.
255-
unsigned NumElements = 1;
256-
if (TheMemory.NumElements != 1 && !InStructSubElement)
257-
NumElements = getElementCountRec(Module, UseTy);
258-
259-
Uses.push_back(PMOMemoryUse(User, Kind, BaseEltNo, NumElements));
158+
Uses.emplace_back(User, Kind);
260159
}
261160

262161
/// Given a tuple_element_addr or struct_element_addr, compute the new
263162
/// BaseEltNo implicit in the selected member, and recursively add uses of
264163
/// the instruction.
265-
bool ElementUseCollector::collectTupleElementUses(TupleElementAddrInst *TEAI,
266-
unsigned BaseEltNo) {
267-
164+
bool ElementUseCollector::collectTupleElementUses(TupleElementAddrInst *TEAI) {
268165
// If we're walking into a tuple within a struct or enum, don't adjust the
269166
// BaseElt. The uses hanging off the tuple_element_addr are going to be
270167
// counted as uses of the struct or enum itself.
271-
if (InStructSubElement)
272-
return collectUses(TEAI, BaseEltNo);
273-
274-
// tuple_element_addr P, 42 indexes into the current tuple element.
275-
// Recursively process its uses with the adjusted element number.
276-
unsigned FieldNo = TEAI->getFieldNo();
277-
auto T = TEAI->getOperand()->getType();
278-
if (T.is<TupleType>()) {
279-
for (unsigned i = 0; i != FieldNo; ++i) {
280-
SILType EltTy = T.getTupleElementType(i);
281-
BaseEltNo += getElementCountRec(Module, EltTy);
282-
}
283-
}
284-
285-
return collectUses(TEAI, BaseEltNo);
168+
return collectUses(TEAI);
286169
}
287170

288-
bool ElementUseCollector::collectStructElementUses(StructElementAddrInst *SEAI,
289-
unsigned BaseEltNo) {
171+
bool ElementUseCollector::collectStructElementUses(
172+
StructElementAddrInst *SEAI) {
290173
// Generally, we set the "InStructSubElement" flag and recursively process
291174
// the uses so that we know that we're looking at something within the
292175
// current element.
293176
llvm::SaveAndRestore<bool> X(InStructSubElement, true);
294-
return collectUses(SEAI, BaseEltNo);
177+
return collectUses(SEAI);
295178
}
296179

297180
bool ElementUseCollector::collectContainerUses(AllocBoxInst *ABI) {
@@ -307,24 +190,23 @@ bool ElementUseCollector::collectContainerUses(AllocBoxInst *ABI) {
307190
continue;
308191

309192
if (auto project = dyn_cast<ProjectBoxInst>(User)) {
310-
if (!collectUses(project, project->getFieldIndex()))
193+
if (!collectUses(project))
311194
return false;
312195
continue;
313196
}
314197

315-
// Other uses of the container are considered escapes of the values.
316-
for (unsigned field :
317-
indices(ABI->getBoxType()->getLayout()->getFields())) {
318-
addElementUses(field,
319-
ABI->getBoxType()->getFieldType(ABI->getModule(), field),
320-
User, PMOUseKind::Escape);
321-
}
198+
// Other uses of the container are considered escapes of the underlying
199+
// value.
200+
//
201+
// This will cause the dataflow to stop propagating any information at the
202+
// use block.
203+
addElementUses(User, PMOUseKind::Escape);
322204
}
323205

324206
return true;
325207
}
326208

327-
bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
209+
bool ElementUseCollector::collectUses(SILValue Pointer) {
328210
assert(Pointer->getType().isAddress() &&
329211
"Walked through the pointer to the value?");
330212
SILType PointeeType = Pointer->getType().getObjectType();
@@ -340,21 +222,21 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
340222

341223
// struct_element_addr P, #field indexes into the current element.
342224
if (auto *SEAI = dyn_cast<StructElementAddrInst>(User)) {
343-
if (!collectStructElementUses(SEAI, BaseEltNo))
225+
if (!collectStructElementUses(SEAI))
344226
return false;
345227
continue;
346228
}
347229

348230
// Instructions that compute a subelement are handled by a helper.
349231
if (auto *TEAI = dyn_cast<TupleElementAddrInst>(User)) {
350-
if (!collectTupleElementUses(TEAI, BaseEltNo))
232+
if (!collectTupleElementUses(TEAI))
351233
return false;
352234
continue;
353235
}
354236

355237
// Look through begin_access.
356238
if (auto I = dyn_cast<BeginAccessInst>(User)) {
357-
if (!collectUses(I, BaseEltNo))
239+
if (!collectUses(I))
358240
return false;
359241
continue;
360242
}
@@ -369,15 +251,15 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
369251
if (PointeeType.is<TupleType>())
370252
UsesToScalarize.push_back(User);
371253
else
372-
addElementUses(BaseEltNo, PointeeType, User, PMOUseKind::Load);
254+
addElementUses(User, PMOUseKind::Load);
373255
continue;
374256
}
375257

376-
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
377-
if (isa<Load##Name##Inst>(User)) { \
378-
Uses.push_back(PMOMemoryUse(User, PMOUseKind::Load, BaseEltNo, 1)); \
379-
continue; \
380-
}
258+
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
259+
if (isa<Load##Name##Inst>(User)) { \
260+
Uses.emplace_back(User, PMOUseKind::Load); \
261+
continue; \
262+
}
381263
#include "swift/AST/ReferenceStorage.def"
382264

383265
// Stores *to* the allocation are writes.
@@ -397,24 +279,24 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
397279
else
398280
Kind = PMOUseKind::Initialization;
399281

400-
addElementUses(BaseEltNo, PointeeType, User, Kind);
282+
addElementUses(User, Kind);
401283
continue;
402284
}
403285

404-
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
405-
if (auto *SI = dyn_cast<Store##Name##Inst>(User)) { \
406-
if (UI->getOperandNumber() == 1) { \
407-
PMOUseKind Kind; \
408-
if (InStructSubElement) \
409-
Kind = PMOUseKind::PartialStore; \
410-
else if (SI->isInitializationOfDest()) \
411-
Kind = PMOUseKind::Initialization; \
412-
else \
413-
Kind = PMOUseKind::Assign; \
414-
Uses.push_back(PMOMemoryUse(User, Kind, BaseEltNo, 1)); \
415-
continue; \
416-
} \
417-
}
286+
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
287+
if (auto *SI = dyn_cast<Store##Name##Inst>(User)) { \
288+
if (UI->getOperandNumber() == 1) { \
289+
PMOUseKind Kind; \
290+
if (InStructSubElement) \
291+
Kind = PMOUseKind::PartialStore; \
292+
else if (SI->isInitializationOfDest()) \
293+
Kind = PMOUseKind::Initialization; \
294+
else \
295+
Kind = PMOUseKind::Assign; \
296+
Uses.emplace_back(User, Kind); \
297+
continue; \
298+
} \
299+
}
418300
#include "swift/AST/ReferenceStorage.def"
419301

420302
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
@@ -439,7 +321,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
439321
else
440322
Kind = PMOUseKind::Assign;
441323

442-
addElementUses(BaseEltNo, PointeeType, User, Kind);
324+
addElementUses(User, Kind);
443325
continue;
444326
}
445327

@@ -464,8 +346,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
464346
if (InStructSubElement) {
465347
return false;
466348
}
467-
addElementUses(BaseEltNo, PointeeType, User,
468-
PMOUseKind::Initialization);
349+
addElementUses(User, PMOUseKind::Initialization);
469350
continue;
470351

471352
// Otherwise, adjust the argument index.
@@ -486,7 +367,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
486367
case ParameterConvention::Indirect_In:
487368
case ParameterConvention::Indirect_In_Constant:
488369
case ParameterConvention::Indirect_In_Guaranteed:
489-
addElementUses(BaseEltNo, PointeeType, User, PMOUseKind::IndirectIn);
370+
addElementUses(User, PMOUseKind::IndirectIn);
490371
continue;
491372

492373
// If this is an @inout parameter, it is like both a load and store.
@@ -496,7 +377,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
496377
// mutating method, we model that as an escape of self. If an
497378
// individual sub-member is passed as inout, then we model that as an
498379
// inout use.
499-
addElementUses(BaseEltNo, PointeeType, User, PMOUseKind::InOutUse);
380+
addElementUses(User, PMOUseKind::InOutUse);
500381
continue;
501382
}
502383
}
@@ -509,15 +390,14 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
509390
if (InStructSubElement) {
510391
return false;
511392
}
512-
Uses.push_back(
513-
PMOMemoryUse(User, PMOUseKind::Initialization, BaseEltNo, 1));
393+
Uses.push_back(PMOMemoryUse(User, PMOUseKind::Initialization));
514394
continue;
515395
}
516396

517397
// open_existential_addr is a use of the protocol value,
518398
// so it is modeled as a load.
519399
if (isa<OpenExistentialAddrInst>(User)) {
520-
Uses.push_back(PMOMemoryUse(User, PMOUseKind::Load, BaseEltNo, 1));
400+
Uses.push_back(PMOMemoryUse(User, PMOUseKind::Load));
521401
// TODO: Is it safe to ignore all uses of the open_existential_addr?
522402
continue;
523403
}
@@ -538,7 +418,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
538418
continue;
539419

540420
// Otherwise, the use is something complicated, it escapes.
541-
addElementUses(BaseEltNo, PointeeType, User, PMOUseKind::Escape);
421+
addElementUses(User, PMOUseKind::Escape);
542422
}
543423

544424
// Now that we've walked all of the immediate uses, scalarize any operations
@@ -604,8 +484,7 @@ bool ElementUseCollector::collectUses(SILValue Pointer, unsigned BaseEltNo) {
604484
// element address computations to recursively process it. This can cause
605485
// further scalarization.
606486
if (llvm::any_of(ElementAddrs, [&](SILValue V) {
607-
return !collectTupleElementUses(cast<TupleElementAddrInst>(V),
608-
BaseEltNo);
487+
return !collectTupleElementUses(cast<TupleElementAddrInst>(V));
609488
})) {
610489
return false;
611490
}

0 commit comments

Comments
 (0)