Skip to content

Commit d689823

Browse files
authored
Merge pull request #65295 from rjmccall/vanishing-tuple-results
Handle vanishing tuples when emitting a result plan into an initalization
2 parents ff62be1 + e87fbc8 commit d689823

File tree

3 files changed

+71
-18
lines changed

3 files changed

+71
-18
lines changed

lib/SILGen/ResultPlan.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ class PackExpansionResultPlan : public ResultPlan {
430430
public:
431431
PackExpansionResultPlan(ResultPlanBuilder &builder,
432432
SILValue packAddr,
433-
Optional<MutableArrayRef<InitializationPtr>> inits,
433+
Optional<ArrayRef<Initialization*>> inits,
434434
AbstractionPattern origExpansionType,
435435
CanTupleEltTypeArrayRef substEltTypes)
436436
: PackAddr(packAddr) {
@@ -443,7 +443,7 @@ class PackExpansionResultPlan : public ResultPlan {
443443

444444
ComponentPlans.reserve(substEltTypes.size());
445445
for (auto i : indices(substEltTypes)) {
446-
Initialization *init = inits ? (*inits)[i].get() : nullptr;
446+
Initialization *init = inits ? (*inits)[i] : nullptr;
447447
CanType substEltType = substEltTypes[i];
448448

449449
if (isa<PackExpansionType>(substEltType)) {
@@ -635,33 +635,49 @@ class TupleRValueResultPlan final : public ResultPlan {
635635
class TupleInitializationResultPlan final : public ResultPlan {
636636
Initialization *tupleInit;
637637
SmallVector<InitializationPtr, 4> eltInitsBuffer;
638-
MutableArrayRef<InitializationPtr> eltInits;
639638
SmallVector<ResultPlanPtr, 4> eltPlans;
639+
bool origTupleVanishes;
640640

641641
public:
642642
TupleInitializationResultPlan(ResultPlanBuilder &builder,
643643
Initialization *tupleInit,
644644
AbstractionPattern origType,
645-
CanType substType)
646-
: tupleInit(tupleInit) {
645+
CanType substType,
646+
bool origTupleVanishes)
647+
: tupleInit(tupleInit), origTupleVanishes(origTupleVanishes) {
648+
647649
// Get the sub-initializations.
648-
eltInits = tupleInit->splitIntoTupleElements(builder.SGF, builder.loc,
649-
substType, eltInitsBuffer);
650+
SmallVector<Initialization*, 4> eltInits;
651+
if (origTupleVanishes) {
652+
eltInits.push_back(tupleInit);
653+
} else {
654+
MutableArrayRef<InitializationPtr> ownedEltInits
655+
= tupleInit->splitIntoTupleElements(builder.SGF, builder.loc,
656+
substType, eltInitsBuffer);
657+
658+
// The ownership of these inits is maintained in eltInitsBuffer
659+
// (or tupleInit internally), but we need to create a temporary
660+
// array of unowned references to the inits, after which we can
661+
// throw away the ArrayRef that was returned to us.
662+
eltInits.reserve(ownedEltInits.size());
663+
for (auto &eltInit : ownedEltInits) {
664+
eltInits.push_back(eltInit.get());
665+
}
666+
}
650667

651668
// Create plans for all the sub-initializations.
652669
eltPlans.reserve(origType.getNumTupleElements());
653-
654670
origType.forEachTupleElement(substType,
655671
[&](TupleElementGenerator &elt) {
656672
auto origEltType = elt.getOrigType();
657673
auto substEltTypes = elt.getSubstTypes();
658674
if (!elt.isOrigPackExpansion()) {
659-
Initialization *eltInit = eltInits[elt.getSubstIndex()].get();
675+
Initialization *eltInit = eltInits[elt.getSubstIndex()];
660676
eltPlans.push_back(builder.build(eltInit, origEltType,
661677
substEltTypes[0]));
662678
} else {
663-
auto componentInits =
664-
eltInits.slice(elt.getSubstIndex(), substEltTypes.size());
679+
auto componentInits = llvm::makeArrayRef(eltInits)
680+
.slice(elt.getSubstIndex(), substEltTypes.size());
665681
eltPlans.push_back(builder.buildForPackExpansion(componentInits,
666682
origEltType,
667683
substEltTypes));
@@ -678,7 +694,12 @@ class TupleInitializationResultPlan final : public ResultPlan {
678694
assert(eltRV.isInContext());
679695
(void)eltRV;
680696
}
681-
tupleInit->finishInitialization(SGF);
697+
698+
// Finish the tuple initialization; but if the tuple vanished,
699+
// this is handled in the loop above.
700+
if (!origTupleVanishes) {
701+
tupleInit->finishInitialization(SGF);
702+
}
682703

683704
return RValue::forInContext();
684705
}
@@ -1179,7 +1200,7 @@ ResultPlanPtr ResultPlanBuilder::buildForScalar(Initialization *init,
11791200
}
11801201

11811202
ResultPlanPtr ResultPlanBuilder::
1182-
buildForPackExpansion(Optional<MutableArrayRef<InitializationPtr>> inits,
1203+
buildForPackExpansion(Optional<ArrayRef<Initialization*>> inits,
11831204
AbstractionPattern origExpansionType,
11841205
CanTupleEltTypeArrayRef substTypes) {
11851206
assert(!inits || inits->size() == substTypes.size());
@@ -1301,10 +1322,16 @@ ResultPlanBuilder::buildScalarIntoPack(SILValue packAddr,
13011322
ResultPlanPtr ResultPlanBuilder::buildForTuple(Initialization *init,
13021323
AbstractionPattern origType,
13031324
CanType substType) {
1304-
// If we have an initialization, and we can split it, do so.
1305-
if (init && init->canSplitIntoTupleElements()) {
1306-
return ResultPlanPtr(
1307-
new TupleInitializationResultPlan(*this, init, origType, substType));
1325+
// If we have an initialization, and we can split the initialization,
1326+
// emit directly into the initialization. If the orig tuple vanishes,
1327+
// that counts as the initialization being splittable.
1328+
if (init) {
1329+
bool vanishes = origType.getVanishingTupleElementPatternType().hasValue();
1330+
if (vanishes || init->canSplitIntoTupleElements()) {
1331+
return ResultPlanPtr(
1332+
new TupleInitializationResultPlan(*this, init, origType, substType,
1333+
vanishes));
1334+
}
13081335
}
13091336

13101337
auto substTupleType = dyn_cast<TupleType>(substType);

lib/SILGen/ResultPlan.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ struct ResultPlanBuilder {
9898
ResultPlanPtr buildForTuple(Initialization *emitInto,
9999
AbstractionPattern origType,
100100
CanType substType);
101-
ResultPlanPtr buildForPackExpansion(Optional<MutableArrayRef<InitializationPtr>> inits,
101+
ResultPlanPtr buildForPackExpansion(Optional<ArrayRef<Initialization*>> inits,
102102
AbstractionPattern origExpansionType,
103103
CanTupleEltTypeArrayRef substTypes);
104104
ResultPlanPtr buildPackExpansionIntoPack(SILValue packAddr,

test/SILGen/variadic-generic-vanishing-tuples.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,29 @@ public func testArgPassingExpansion<X>(arg: G<X>) {
7575
public func testArgPassingPartial() {
7676
Holder< >.takePartial(arg: 0)
7777
}
78+
79+
func makeTuple<each T>(_ t: repeat each T) -> (repeat each T) {
80+
return (repeat each t)
81+
}
82+
83+
// rdar://107972801
84+
// CHECK-LABEL: sil {{.*}}@$s4main7makeOneyxxlF : $@convention(thin) <T> (@in_guaranteed T) -> @out T {
85+
// CHECK: bb0(%0 : $*T, %1 : $*T):
86+
// CHECK: [[RET_PACK:%.*]] = alloc_pack $Pack{T}
87+
// CHECK-NEXT: [[INDEX:%.*]] = scalar_pack_index 0 of $Pack{T}
88+
// CHECK-NEXT: pack_element_set %0 : $*T into [[INDEX]] of [[RET_PACK]] :
89+
// CHECK-NEXT: [[ARG_PACK:%.*]] = alloc_pack $Pack{T}
90+
// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $T
91+
// CHECK-NEXT: copy_addr %1 to [init] [[TEMP]] : $*T
92+
// CHECK-NEXT: [[INDEX:%.*]] = scalar_pack_index 0 of $Pack{T}
93+
// CHECK-NEXT: pack_element_set [[TEMP]] : $*T into [[INDEX]] of [[ARG_PACK]] :
94+
// CHECK-NEXT: // function_ref
95+
// CHECK-NEXT: [[FN:%.*]] = function_ref @$s4main9makeTupleyxxQp_txxQpRvzlF : $@convention(thin) <each τ_0_0> (@pack_guaranteed Pack{repeat each τ_0_0}) -> @pack_out Pack{repeat each τ_0_0}
96+
// CHECK-NEXT: apply [[FN]]<Pack{T}>([[RET_PACK]], [[ARG_PACK]])
97+
// CHECK-NEXT: destroy_addr [[TEMP]] : $*T
98+
// CHECK-NEXT: dealloc_stack [[TEMP]] : $*T
99+
// CHECK-NEXT: dealloc_pack [[ARG_PACK]] : $*Pack{T}
100+
// CHECK-NEXT: dealloc_pack [[RET_PACK]] : $*Pack{T}
101+
public func makeOne<T>(_ t: T) -> T {
102+
return makeTuple(t)
103+
}

0 commit comments

Comments
 (0)