Skip to content

Commit a829fa2

Browse files
Merge pull request #79366 from nate-chandler/rdar141718098
[IRGen] Pack: Scope recursive pack allocations.
2 parents 10aac85 + 1102752 commit a829fa2

File tree

3 files changed

+95
-45
lines changed

3 files changed

+95
-45
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 62 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -413,24 +413,23 @@ static void emitPackExpansionPack(
413413
IGF.Builder.emitBlock(loop);
414414
ConditionalDominanceScope condition(IGF);
415415

416-
auto *element = elementForIndex(phi);
416+
IGF.withLocalStackPackAllocs([&]() {
417+
auto *element = elementForIndex(phi);
417418

418-
// Store the element metadata into to the current destination index.
419-
auto *eltIndex = IGF.Builder.CreateAdd(dynamicIndex, phi);
420-
Address eltPtr(
421-
IGF.Builder.CreateInBoundsGEP(pack.getElementType(),
422-
pack.getAddress(),
423-
eltIndex),
424-
pack.getElementType(),
425-
pack.getAlignment());
419+
// Store the element metadata into to the current destination index.
420+
auto *eltIndex = IGF.Builder.CreateAdd(dynamicIndex, phi);
421+
Address eltPtr(IGF.Builder.CreateInBoundsGEP(pack.getElementType(),
422+
pack.getAddress(), eltIndex),
423+
pack.getElementType(), pack.getAlignment());
426424

427-
IGF.Builder.CreateStore(element, eltPtr);
425+
IGF.Builder.CreateStore(element, eltPtr);
426+
});
428427

429428
// Increment our counter.
430429
auto *next = IGF.Builder.CreateAdd(phi,
431430
llvm::ConstantInt::get(IGF.IGM.SizeTy, 1));
432431

433-
phi->addIncoming(next, loop);
432+
phi->addIncoming(next, IGF.Builder.GetInsertBlock());
434433

435434
// Repeat the loop.
436435
IGF.Builder.CreateBr(check);
@@ -717,6 +716,20 @@ void IRGenFunction::eraseStackPackWitnessTableAlloc(StackAddress addr,
717716
(void)removed;
718717
}
719718

719+
void IRGenFunction::withLocalStackPackAllocs(llvm::function_ref<void()> fn) {
720+
auto oldSize = OutstandingStackPackAllocs.size();
721+
fn();
722+
SmallVector<StackPackAlloc, 2> allocs;
723+
for (auto index = oldSize, size = OutstandingStackPackAllocs.size();
724+
index < size; ++index) {
725+
allocs.push_back(OutstandingStackPackAllocs[index]);
726+
}
727+
while (OutstandingStackPackAllocs.size() > oldSize) {
728+
OutstandingStackPackAllocs.pop_back();
729+
}
730+
cleanupStackAllocPacks(*this, allocs);
731+
}
732+
720733
llvm::Value *irgen::emitWitnessTablePackRef(IRGenFunction &IGF,
721734
CanPackType packType,
722735
PackConformance *conformance) {
@@ -970,42 +983,46 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
970983
auto *materialize = IGF.createBasicBlock("pack-index-element-metadata");
971984
IGF.Builder.emitBlock(materialize);
972985

973-
llvm::Value *metadata = nullptr;
974-
llvm::SmallVector<llvm::Value *, 2> wtables;
975-
wtables.reserve(conformances.size());
976-
if (auto expansionTy = dyn_cast<PackExpansionType>(elementTy)) {
977-
// Actually materialize %inner. Then use it to get the metadata from the
978-
// pack expansion at that index.
979-
auto *relativeIndex = IGF.Builder.CreateSub(index, lowerBound);
980-
auto context =
981-
OpenedElementContext::createForContextualExpansion(IGF.IGM.Context, expansionTy);
982-
auto patternTy = expansionTy.getPatternType();
983-
metadata = emitPackExpansionElementMetadata(IGF, context, patternTy,
984-
relativeIndex, request);
985-
for (auto conformance : conformances) {
986-
auto patternConformance = conformance.getPack()->getPatternConformances()[i];
987-
auto *wtable = emitPackExpansionElementWitnessTable(
988-
IGF, context, patternTy, patternConformance,
989-
&metadata, relativeIndex);
990-
wtables.push_back(wtable);
986+
IGF.withLocalStackPackAllocs([&]() {
987+
llvm::Value *metadata = nullptr;
988+
llvm::SmallVector<llvm::Value *, 2> wtables;
989+
wtables.reserve(conformances.size());
990+
if (auto expansionTy = dyn_cast<PackExpansionType>(elementTy)) {
991+
// Actually materialize %inner. Then use it to get the metadata from
992+
// the pack expansion at that index.
993+
auto *relativeIndex = IGF.Builder.CreateSub(index, lowerBound);
994+
auto context = OpenedElementContext::createForContextualExpansion(
995+
IGF.IGM.Context, expansionTy);
996+
auto patternTy = expansionTy.getPatternType();
997+
metadata = emitPackExpansionElementMetadata(IGF, context, patternTy,
998+
relativeIndex, request);
999+
for (auto conformance : conformances) {
1000+
auto patternConformance =
1001+
conformance.getPack()->getPatternConformances()[i];
1002+
auto *wtable = emitPackExpansionElementWitnessTable(
1003+
IGF, context, patternTy, patternConformance, &metadata,
1004+
relativeIndex);
1005+
wtables.push_back(wtable);
1006+
}
1007+
} else {
1008+
metadata = IGF.emitTypeMetadataRef(elementTy, request).getMetadata();
1009+
for (auto conformance : conformances) {
1010+
auto patternConformance =
1011+
conformance.getPack()->getPatternConformances()[i];
1012+
llvm::Value *_metadata = nullptr;
1013+
auto *wtable = emitWitnessTableRef(IGF, elementTy,
1014+
/*srcMetadataCache=*/&_metadata,
1015+
patternConformance);
1016+
wtables.push_back(wtable);
1017+
}
9911018
}
992-
} else {
993-
metadata = IGF.emitTypeMetadataRef(elementTy, request).getMetadata();
994-
for (auto conformance : conformances) {
995-
auto patternConformance = conformance.getPack()->getPatternConformances()[i];
996-
llvm::Value *_metadata = nullptr;
997-
auto *wtable =
998-
emitWitnessTableRef(IGF, elementTy, /*srcMetadataCache=*/&_metadata,
999-
patternConformance);
1000-
wtables.push_back(wtable);
1019+
metadataPhi->addIncoming(metadata, IGF.Builder.GetInsertBlock());
1020+
for (auto i : indices(wtables)) {
1021+
auto *wtable = wtables[i];
1022+
auto *wtablePhi = wtablePhis[i];
1023+
wtablePhi->addIncoming(wtable, IGF.Builder.GetInsertBlock());
10011024
}
1002-
}
1003-
metadataPhi->addIncoming(metadata, IGF.Builder.GetInsertBlock());
1004-
for (auto i : indices(wtables)) {
1005-
auto *wtable = wtables[i];
1006-
auto *wtablePhi = wtablePhis[i];
1007-
wtablePhi->addIncoming(wtable, IGF.Builder.GetInsertBlock());
1008-
}
1025+
});
10091026
IGF.Builder.CreateBr(exit);
10101027
// }} Finished emitting emit_i.
10111028

lib/IRGen/IRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ class IRGenFunction {
437437
void recordStackPackWitnessTableAlloc(StackAddress addr, llvm::Value *shape);
438438
void eraseStackPackWitnessTableAlloc(StackAddress addr, llvm::Value *shape);
439439

440+
void withLocalStackPackAllocs(llvm::function_ref<void()> fn);
441+
440442
/// Emit a load of a reference to the given Objective-C selector.
441443
llvm::Value *emitObjCSelectorRefLoad(StringRef selector);
442444

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
struct S<T> {
5+
let t: T
6+
func f<each A, each B>(
7+
_ b: S<(repeat each B)>
8+
) -> S<(repeat each A, repeat each B)>
9+
where T == (repeat each A) {
10+
S<(repeat each A, repeat each B)>(
11+
t: (repeat each t, repeat each b.t)
12+
)
13+
}
14+
}
15+
16+
func doit() {
17+
let s1 = S(t: ("", ""))
18+
// CHECK: S<(String, String)>(t: ("", ""))
19+
print(s1)
20+
let s2 = s1.f(S(t: (5, 5)))
21+
// CHECK: S<(String, String, Int, Int)>(t: ("", "", 5, 5))
22+
print(s2)
23+
let s3 = s2.f(S(t: (13.1, 26.2)))
24+
// CHECK: S<(String, String, Int, Int, Double, Double)>(t: ("", "", 5, 5, 13.1, 26.2))
25+
print(s3)
26+
let s4 = s3.f(S(t: (S(t: ""), S(t: ""))))
27+
// CHECK: S<(String, String, Int, Int, Double, Double, S<String>, S<String>)>(t: ("", "", 5, 5, 13.1, 26.2, main.S<Swift.String>(t: ""), main.S<Swift.String>(t: "")))
28+
print(s4)
29+
}
30+
31+
doit()

0 commit comments

Comments
 (0)