Skip to content

Commit 2928fc2

Browse files
authored
Merge pull request swiftlang#14672 from gottesmm/tuple_implosion_mv
2 parents fca4493 + 941b74f commit 2928fc2

File tree

3 files changed

+58
-55
lines changed

3 files changed

+58
-55
lines changed

lib/SILGen/RValue.cpp

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -174,24 +174,25 @@ class ExplodeTupleValue
174174

175175
enum class ImplodeKind { Unmanaged, Forward, Copy };
176176

177-
template<ImplodeKind KIND>
177+
template <ImplodeKind KIND>
178178
class ImplodeLoadableTupleValue
179-
: public CanTypeVisitor<ImplodeLoadableTupleValue<KIND>,
180-
/*RetTy=*/ SILValue,
181-
/*Args...=*/ SILLocation>
182-
{
179+
: public CanTypeVisitor<ImplodeLoadableTupleValue<KIND>,
180+
/*RetTy=*/ManagedValue,
181+
/*Args...=*/SILLocation> {
183182
public:
184183
ArrayRef<ManagedValue> values;
185184
SILGenFunction &SGF;
186185

187-
static SILValue getValue(SILGenFunction &SGF, ManagedValue v, SILLocation l) {
186+
static ManagedValue getValue(SILGenFunction &SGF, ManagedValue v,
187+
SILLocation l) {
188188
switch (KIND) {
189189
case ImplodeKind::Unmanaged:
190-
return v.getUnmanagedValue();
190+
assert(!v.hasCleanup());
191+
return v.unmanagedBorrow();
191192
case ImplodeKind::Forward:
192-
return v.ensurePlusOne(SGF, l).forward(SGF);
193+
return v.ensurePlusOne(SGF, l);
193194
case ImplodeKind::Copy:
194-
return v.copyUnmanaged(SGF, l).forward(SGF);
195+
return v.copy(SGF, l);
195196
}
196197

197198
llvm_unreachable("Unhandled ImplodeKind in switch.");
@@ -202,14 +203,14 @@ class ImplodeLoadableTupleValue
202203
: values(values), SGF(SGF)
203204
{}
204205

205-
SILValue visitType(CanType t, SILLocation l) {
206-
SILValue result = getValue(SGF, values[0], l);
206+
ManagedValue visitType(CanType t, SILLocation l) {
207+
ManagedValue result = getValue(SGF, values[0], l);
207208
values = values.slice(1);
208209
return result;
209210
}
210211

211-
SILValue visitTupleType(CanTupleType t, SILLocation l) {
212-
SmallVector<SILValue, 4> elts;
212+
ManagedValue visitTupleType(CanTupleType t, SILLocation l) {
213+
SmallVector<ManagedValue, 4> elts;
213214
for (auto fieldTy : t.getElementTypes())
214215
elts.push_back(this->visit(fieldTy, l));
215216
SILType ty = SGF.getLoweredLoadableType(t);
@@ -220,12 +221,11 @@ class ImplodeLoadableTupleValue
220221
}
221222
};
222223

223-
template<ImplodeKind KIND>
224+
template <ImplodeKind KIND>
224225
class ImplodeAddressOnlyTuple
225-
: public CanTypeVisitor<ImplodeAddressOnlyTuple<KIND>,
226-
/*RetTy=*/ void,
227-
/*Args...=*/ SILValue, SILLocation>
228-
{
226+
: public CanTypeVisitor<ImplodeAddressOnlyTuple<KIND>,
227+
/*RetTy=*/void,
228+
/*Args...=*/Initialization *, SILLocation> {
229229
public:
230230
ArrayRef<ManagedValue> values;
231231
SILGenFunction &SGF;
@@ -235,7 +235,7 @@ class ImplodeAddressOnlyTuple
235235
: values(values), SGF(SGF)
236236
{}
237237

238-
void visitType(CanType t, SILValue address, SILLocation l) {
238+
void visitType(CanType t, Initialization *address, SILLocation l) {
239239
ManagedValue v = values[0];
240240
switch (KIND) {
241241
case ImplodeKind::Unmanaged:
@@ -245,25 +245,30 @@ class ImplodeAddressOnlyTuple
245245
// If a value is forwarded into, we require the value to be at +1. If the
246246
// the value is already at +1, we just forward. Otherwise, we perform the
247247
// copy.
248-
v.ensurePlusOne(SGF, l).forwardInto(SGF, l, address);
248+
address->copyOrInitValueInto(SGF, l, v.ensurePlusOne(SGF, l),
249+
true /*isInit*/);
249250
break;
250251

251252
case ImplodeKind::Copy:
252-
v.copyInto(SGF, address, l);
253+
address->copyOrInitValueInto(SGF, l, v, false /*isInit*/);
253254
break;
254255
}
256+
257+
address->finishInitialization(SGF);
255258
values = values.slice(1);
256259
}
257260

258-
void visitTupleType(CanTupleType t, SILValue address, SILLocation l) {
259-
for (unsigned n = 0, size = t->getNumElements(); n < size; ++n) {
260-
CanType fieldCanTy = t.getElementType(n);
261-
SILType fieldTy = SGF.getLoweredType(fieldCanTy);
262-
SILValue fieldAddr = SGF.B.createTupleElementAddr(l,
263-
address, n,
264-
fieldTy.getAddressType());
265-
this->visit(fieldCanTy, fieldAddr, l);
261+
void visitTupleType(CanTupleType t, Initialization *address, SILLocation l) {
262+
assert(address->canSplitIntoTupleElements());
263+
llvm::SmallVector<InitializationPtr, 4> buf;
264+
auto bufResult = address->splitIntoTupleElements(SGF, l, t, buf);
265+
266+
for (unsigned i : range(t->getNumElements())) {
267+
CanType fieldCanTy = t.getElementType(i);
268+
this->visit(fieldCanTy, bufResult[i].get(), l);
266269
}
270+
271+
address->finishInitialization(SGF);
267272
}
268273

269274
~ImplodeAddressOnlyTuple() {
@@ -273,27 +278,27 @@ class ImplodeAddressOnlyTuple
273278

274279
} // end anonymous namespace
275280

276-
template<ImplodeKind KIND>
277-
static SILValue implodeTupleValues(ArrayRef<ManagedValue> values,
278-
SILGenFunction &SGF,
279-
CanType tupleType, SILLocation l) {
281+
template <ImplodeKind KIND>
282+
static ManagedValue implodeTupleValues(ArrayRef<ManagedValue> values,
283+
SILGenFunction &SGF, CanType tupleType,
284+
SILLocation l) {
280285
// Non-tuples don't need to be imploded.
281286
if (!isa<TupleType>(tupleType)) {
282287
assert(values.size() == 1 && "exploded non-tuple value?!");
283288
return ImplodeLoadableTupleValue<KIND>::getValue(SGF, values[0], l);
284289
}
285290

286-
SILType loweredType = SGF.getLoweredType(tupleType);
291+
const auto &TL = SGF.getTypeLowering(tupleType);
287292

288293
// To implode an address-only tuple, we need to create a buffer to hold the
289294
// result tuple.
290-
if (loweredType.isAddressOnly(SGF.getModule()) &&
291-
SGF.silConv.useLoweredAddresses()) {
295+
if (TL.isAddressOnly() && SGF.silConv.useLoweredAddresses()) {
292296
assert(KIND != ImplodeKind::Unmanaged &&
293297
"address-only values are always managed!");
294-
SILValue buffer = SGF.emitTemporaryAllocation(l, loweredType);
295-
ImplodeAddressOnlyTuple<KIND>(values, SGF).visit(tupleType, buffer, l);
296-
return buffer;
298+
auto buffer = SGF.emitTemporary(l, TL);
299+
ImplodeAddressOnlyTuple<KIND>(values, SGF)
300+
.visit(tupleType, buffer.get(), l);
301+
return buffer->getManagedAddress();
297302
}
298303

299304
// To implode loadable tuples, we just need to combine the elements with
@@ -363,13 +368,12 @@ static void copyOrInitValuesInto(Initialization *init,
363368
// Otherwise, process this by turning the values corresponding to the tuple
364369
// into a single value (through an implosion) and then binding that value to
365370
// our initialization.
366-
SILValue scalar = implodeTupleValues<KIND>(values, SGF, type, loc);
367-
371+
ManagedValue scalar = implodeTupleValues<KIND>(values, SGF, type, loc);
372+
368373
// This will have just used up the first values in the list, pop them off.
369374
values = values.slice(getRValueSize(type));
370-
371-
init->copyOrInitValueInto(SGF, loc, ManagedValue::forUnmanaged(scalar),
372-
isInit);
375+
376+
init->copyOrInitValueInto(SGF, loc, scalar, isInit);
373377
init->finishInitialization(SGF);
374378
}
375379

@@ -513,11 +517,10 @@ void RValue::addElement(SILGenFunction &SGF, ManagedValue element,
513517

514518
SILValue RValue::forwardAsSingleValue(SILGenFunction &SGF, SILLocation l) && {
515519
assert(isComplete() && "rvalue is not complete");
516-
// *NOTE* Inside implodeTupleValues, we copy our values if they are not at +1.
517-
SILValue result
518-
= implodeTupleValues<ImplodeKind::Forward>(values, SGF, type, l);
520+
assert(!isUsed() && "rvalue was used?!");
521+
ManagedValue mv = std::move(*this).getAsSingleValue(SGF, l);
519522
makeUsed();
520-
return result;
523+
return mv.forward(SGF);
521524
}
522525

523526
SILValue RValue::forwardAsSingleStorageValue(SILGenFunction &SGF,
@@ -593,16 +596,16 @@ ManagedValue RValue::getAsSingleValue(SILGenFunction &SGF, SILLocation loc) && {
593596
return result;
594597
}
595598

596-
// Forward into a single value, then install a cleanup on the resulting
597-
// imploded value if we have a +1 rvalue.
598-
CleanupCloner cloner(SGF, *this);
599-
return cloner.clone(std::move(*this).forwardAsSingleValue(SGF, loc));
599+
// *NOTE* Inside implodeTupleValues, we copy our values if they are not at +1.
600+
return implodeTupleValues<ImplodeKind::Forward>(values, SGF, type, loc);
600601
}
601602

602603
SILValue RValue::getUnmanagedSingleValue(SILGenFunction &SGF,
603604
SILLocation l) const & {
604605
assert(isComplete() && "rvalue is not complete");
605-
return implodeTupleValues<ImplodeKind::Unmanaged>(values, SGF, type, l);
606+
ManagedValue mv =
607+
implodeTupleValues<ImplodeKind::Unmanaged>(values, SGF, type, l);
608+
return mv.getValue();
606609
}
607610

608611
void RValue::forwardAll(SILGenFunction &SGF,

lib/SILGen/SILGenBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ ManagedValue SILGenBuilder::createTuple(SILLocation loc, SILType type,
808808
// We need to look for the first non-trivial value and use that as our cleanup
809809
// cloner value.
810810
auto iter = find_if(elements, [&](ManagedValue mv) -> bool {
811-
return mv.getType().isTrivial(getModule());
811+
return !mv.getType().isTrivial(getModule());
812812
});
813813

814814
llvm::SmallVector<SILValue, 8> forwardedValues;

test/SILGen/guaranteed_normal_args.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,10 @@ extension FakeDictionary {
185185
// CHECK: [[X_1:%.*]] = tuple_element_addr [[X]] : $*(Key, Value), 1
186186
// CHECK: [[TMP_X:%.*]] = alloc_stack $(Key, Value)
187187
// CHECK: [[TMP_X_0:%.*]] = tuple_element_addr [[TMP_X]] : $*(Key, Value), 0
188+
// CHECK: [[TMP_X_1:%.*]] = tuple_element_addr [[TMP_X]] : $*(Key, Value), 1
188189
// CHECK: [[TMP_0:%.*]] = alloc_stack $Key
189190
// CHECK: copy_addr [[X_0]] to [initialization] [[TMP_0]]
190191
// CHECK: copy_addr [take] [[TMP_0]] to [initialization] [[TMP_X_0]]
191-
// CHECK: [[TMP_X_1:%.*]] = tuple_element_addr [[TMP_X]] : $*(Key, Value), 1
192192
// CHECK: [[TMP_1:%.*]] = alloc_stack $Value
193193
// CHECK: copy_addr [[X_1]] to [initialization] [[TMP_1]]
194194
// CHECK: copy_addr [take] [[TMP_1]] to [initialization] [[TMP_X_1]]

0 commit comments

Comments
 (0)