Skip to content

Commit 6267860

Browse files
committed
IRGen: Remove initializeBufferWithTakeOfBuffer in favor of memcpy
And update the existential container's initializeWithTake implementation in the runtime. After only allowing bitwise takable values in the inline buffer we can use memcpy to move existential container values. rdar://31414907 SR-343
1 parent d05f611 commit 6267860

36 files changed

+121
-496
lines changed

include/swift/ABI/ValueWitness.def

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,6 @@ FUNCTION_VALUE_WITNESS(assignWithTake,
172172
MUTABLE_VALUE_TYPE,
173173
(MUTABLE_VALUE_TYPE, MUTABLE_VALUE_TYPE, TYPE_TYPE))
174174

175-
/// T *(*initializeBufferWithTakeOfBuffer)(B *dest, B *src, M *self);
176-
/// Given an invalid buffer, initialize it by taking the value out of
177-
/// the source buffer.
178-
FUNCTION_VALUE_WITNESS(initializeBufferWithTakeOfBuffer,
179-
InitializeBufferWithTakeOfBuffer,
180-
MUTABLE_VALUE_TYPE,
181-
(MUTABLE_BUFFER_TYPE, MUTABLE_BUFFER_TYPE, TYPE_TYPE))
182-
183175
/// unsigned (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases)
184176
/// Given an instance of valid single payload enum with a payload of this
185177
/// witness table's type (e.g Optional<ThisType>) , get the tag of the enum.

lib/IRGen/GenExistential.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,11 @@ class OpaqueExistentialTypeInfo final :
343343
void initializeWithTake(IRGenFunction &IGF, Address dest, Address src,
344344
SILType T, bool isOutlined) const override {
345345
if (isOutlined) {
346-
llvm::Value *metadata = copyType(IGF, dest, src);
347-
348-
auto layout = getLayout();
349-
350-
// Project down to the buffers and ask the witnesses to do a
351-
// take-initialize.
352-
Address srcBuffer = layout.projectExistentialBuffer(IGF, src);
353-
Address destBuffer = layout.projectExistentialBuffer(IGF, dest);
354-
emitInitializeBufferWithTakeOfBufferCall(IGF, metadata, destBuffer,
355-
srcBuffer);
346+
// memcpy the existential container. This is safe because: either the
347+
// value is stored inline and is therefore by convention bitwise takable
348+
// or the value is stored in a reference counted heap buffer, in which
349+
// case a memcpy of the reference is also correct.
350+
IGF.emitMemCpy(dest, src, getLayout().getSize(IGF.IGM));
356351
} else {
357352
// Create an outlined function to avoid explosion
358353
OutliningMetadataCollector collector(IGF);

lib/IRGen/GenOpaque.cpp

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,7 @@ static llvm::Type *createWitnessType(IRGenModule &IGM, ValueWitness index) {
6666
}
6767

6868
// T *(*initializeBufferWithCopyOfBuffer)(B *dest, B *src, M *self);
69-
// T *(*initializeBufferWithTakeOfBuffer)(B *dest, B *src, M *self);
70-
case ValueWitness::InitializeBufferWithCopyOfBuffer:
71-
case ValueWitness::InitializeBufferWithTakeOfBuffer: {
69+
case ValueWitness::InitializeBufferWithCopyOfBuffer: {
7270
llvm::Type *bufPtrTy = IGM.getFixedBufferTy()->getPointerTo(0);
7371
llvm::Type *args[] = { bufPtrTy, bufPtrTy, IGM.TypeMetadataPtrTy };
7472
return llvm::FunctionType::get(IGM.OpaquePtrTy, args, /*isVarArg*/ false);
@@ -212,7 +210,6 @@ static llvm::AttributeList getValueWitnessAttrs(IRGenModule &IGM,
212210
// These have two arguments and they don't alias each other.
213211
case ValueWitness::AssignWithTake:
214212
case ValueWitness::InitializeBufferWithCopyOfBuffer:
215-
case ValueWitness::InitializeBufferWithTakeOfBuffer:
216213
case ValueWitness::InitializeWithCopy:
217214
case ValueWitness::InitializeWithTake:
218215
return attrs.addAttribute(ctx, 1, llvm::Attribute::NoAlias)
@@ -259,8 +256,6 @@ static StringRef getValueWitnessLabel(ValueWitness index) {
259256
return "initializeWithCopy";
260257
case ValueWitness::InitializeWithTake:
261258
return "initializeWithTake";
262-
case ValueWitness::InitializeBufferWithTakeOfBuffer:
263-
return "initializeBufferWithTakeOfBuffer";
264259
case ValueWitness::Size:
265260
return "size";
266261
case ValueWitness::Flags:
@@ -417,31 +412,6 @@ irgen::emitInitializeBufferWithCopyOfBufferCall(IRGenFunction &IGF,
417412
return call;
418413
}
419414

420-
llvm::Value *
421-
irgen::emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
422-
SILType T,
423-
Address destBuffer,
424-
Address srcBuffer) {
425-
auto metadata = IGF.emitTypeMetadataRefForLayout(T);
426-
return emitInitializeBufferWithTakeOfBufferCall(IGF, metadata,
427-
destBuffer, srcBuffer);
428-
}
429-
430-
/// Emit a call to do an 'initializeBufferWithTakeOfBuffer' operation.
431-
llvm::Value *
432-
irgen::emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
433-
llvm::Value *metadata,
434-
Address destBuffer,
435-
Address srcBuffer) {
436-
auto copyFn = emitLoadOfValueWitnessFunctionFromMetadata(IGF, metadata,
437-
ValueWitness::InitializeBufferWithTakeOfBuffer);
438-
llvm::CallInst *call =
439-
IGF.Builder.CreateCall(copyFn,
440-
{destBuffer.getAddress(), srcBuffer.getAddress(), metadata});
441-
442-
return call;
443-
}
444-
445415
/// Emit a dynamic alloca call to allocate enough memory to hold an object of
446416
/// type 'T' and an optional llvm.stackrestore point if 'isInEntryBlock' is
447417
/// false.

lib/IRGen/GenOpaque.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,6 @@ namespace irgen {
5858
Address destBuffer,
5959
Address srcBuffer);
6060

61-
/// Emit a call to do an 'initializeBufferWithTakeOfBuffer' operation.
62-
llvm::Value *emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
63-
llvm::Value *metadata,
64-
Address destBuffer,
65-
Address srcBuffer);
66-
67-
/// Emit a call to do an 'initializeBufferWithTakeOfBuffer' operation.
68-
llvm::Value *emitInitializeBufferWithTakeOfBufferCall(IRGenFunction &IGF,
69-
SILType T,
70-
Address destBuffer,
71-
Address srcBuffer);
72-
7361
/// Emit a call to do an 'initializeWithCopy' operation.
7462
void emitInitializeWithCopyCall(IRGenFunction &IGF,
7563
SILType T,

lib/IRGen/GenRecord.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -323,22 +323,6 @@ class RecordTypeInfo<Impl, Base, FieldImpl,
323323
public:
324324
using super::getStorageType;
325325

326-
Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
327-
Address destBuffer,
328-
Address srcBuffer,
329-
SILType type) const override {
330-
if (auto field = getUniqueNonEmptyField()) {
331-
auto &fieldTI = field->getTypeInfo();
332-
Address fieldResult =
333-
fieldTI.initializeBufferWithTakeOfBuffer(IGF, destBuffer, srcBuffer,
334-
field->getType(IGF.IGM, type));
335-
return IGF.Builder.CreateElementBitCast(fieldResult, getStorageType());
336-
} else {
337-
return super::initializeBufferWithTakeOfBuffer(IGF, destBuffer,
338-
srcBuffer, type);
339-
}
340-
}
341-
342326
Address initializeBufferWithCopyOfBuffer(IRGenFunction &IGF,
343327
Address destBuffer,
344328
Address srcBuffer,

lib/IRGen/GenValueWitness.cpp

Lines changed: 0 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ const char *irgen::getValueWitnessName(ValueWitness witness) {
5656
CASE(InitializeBufferWithCopyOfBuffer)
5757
CASE(InitializeWithCopy)
5858
CASE(InitializeWithTake)
59-
CASE(InitializeBufferWithTakeOfBuffer)
6059
CASE(StoreExtraInhabitant)
6160
CASE(GetExtraInhabitantIndex)
6261
CASE(GetEnumTag)
@@ -331,47 +330,6 @@ static Address emitDefaultInitializeBufferWithCopyOfBuffer(
331330
}
332331
}
333332

334-
/// Emit an 'initializeBufferWithTakeOfBuffer' operation.
335-
/// Returns the address of the destination object.
336-
static Address
337-
emitDefaultInitializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
338-
Address destBuffer,
339-
Address srcBuffer,
340-
SILType T,
341-
const TypeInfo &type,
342-
FixedPacking packing) {
343-
switch (packing) {
344-
345-
case FixedPacking::Dynamic:
346-
// Special-case dynamic packing in order to thread the jumps.
347-
return emitForDynamicPacking(IGF,
348-
&emitDefaultInitializeBufferWithTakeOfBuffer,
349-
T, type, destBuffer, srcBuffer);
350-
351-
case FixedPacking::OffsetZero: {
352-
// Both of these allocations/projections should be no-ops.
353-
Address destObject =
354-
emitDefaultAllocateBuffer(IGF, destBuffer, T, type, packing);
355-
Address srcObject =
356-
emitDefaultProjectBuffer(IGF, srcBuffer, T, type, packing);
357-
type.initializeWithTake(IGF, destObject, srcObject, T, true);
358-
return destObject;
359-
}
360-
361-
case FixedPacking::Allocate: {
362-
// Just copy the out-of-line storage pointers.
363-
srcBuffer = IGF.Builder.CreateBitCast(
364-
srcBuffer, IGF.IGM.RefCountedPtrTy->getPointerTo());
365-
llvm::Value *addr = IGF.Builder.CreateLoad(srcBuffer);
366-
destBuffer = IGF.Builder.CreateBitCast(
367-
destBuffer, IGF.IGM.RefCountedPtrTy->getPointerTo());
368-
IGF.Builder.CreateStore(addr, destBuffer);
369-
return emitDefaultProjectBuffer(IGF, destBuffer, T, type, packing);
370-
}
371-
}
372-
llvm_unreachable("bad fixed packing");
373-
}
374-
375333
// Metaprogram some of the common boilerplate here:
376334
// - the default implementation in TypeInfo
377335
// - the value-witness emitter which tries to avoid some dynamic
@@ -392,8 +350,6 @@ static Address emit##TITLE(IRGenFunction &IGF, Address dest, Address src, \
392350
}
393351
DEFINE_BINARY_BUFFER_OP(initializeBufferWithCopyOfBuffer,
394352
InitializeBufferWithCopyOfBuffer)
395-
DEFINE_BINARY_BUFFER_OP(initializeBufferWithTakeOfBuffer,
396-
InitializeBufferWithTakeOfBuffer)
397353
#undef DEFINE_BINARY_BUFFER_OP
398354

399355

@@ -532,19 +488,6 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
532488
return;
533489
}
534490

535-
case ValueWitness::InitializeBufferWithTakeOfBuffer: {
536-
Address dest = getArgAsBuffer(IGF, argv, "dest");
537-
Address src = getArgAsBuffer(IGF, argv, "src");
538-
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
539-
540-
Address result =
541-
emitInitializeBufferWithTakeOfBuffer(IGF, dest, src, concreteType,
542-
type, packing);
543-
result = IGF.Builder.CreateBitCast(result, IGF.IGM.OpaquePtrTy);
544-
IGF.Builder.CreateRet(result.getAddress());
545-
return;
546-
}
547-
548491
case ValueWitness::InitializeWithCopy: {
549492
Address dest = getArgAs(IGF, argv, type, "dest");
550493
Address src = getArgAs(IGF, argv, type, "src");
@@ -805,38 +748,6 @@ static llvm::Constant *getMemCpyFunction(IRGenModule &IGM,
805748
});
806749
}
807750

808-
/// Return a function which takes two buffer arguments, copies
809-
/// a pointer from the second to the first, and returns the pointer.
810-
static llvm::Constant *
811-
getCopyOutOfLineBoxPointerFunction(IRGenModule &IGM,
812-
const FixedTypeInfo &fixedTI) {
813-
llvm::Type *argTys[] = { IGM.Int8PtrPtrTy, IGM.Int8PtrPtrTy,
814-
IGM.TypeMetadataPtrTy };
815-
llvm::SmallString<40> name;
816-
{
817-
llvm::raw_svector_ostream nameStream(name);
818-
nameStream << "__swift_copy_outline_existential_box_pointer";
819-
nameStream << fixedTI.getFixedAlignment().getValue();
820-
}
821-
return IGM.getOrCreateHelperFunction(
822-
name, IGM.Int8PtrTy, argTys, [&](IRGenFunction &IGF) {
823-
auto it = IGF.CurFn->arg_begin();
824-
Address dest(&*it++, IGM.getPointerAlignment());
825-
Address src(&*it++, IGM.getPointerAlignment());
826-
auto *ptr = IGF.Builder.CreateLoad(src);
827-
IGF.Builder.CreateStore(ptr, dest);
828-
auto *alignmentMask = fixedTI.getStaticAlignmentMask(IGM);
829-
auto *heapHeaderSize = llvm::ConstantInt::get(
830-
IGM.SizeTy, IGM.RefCountedStructSize.getValue());
831-
auto *startOffset = IGF.Builder.CreateAnd(
832-
IGF.Builder.CreateAdd(heapHeaderSize, alignmentMask),
833-
IGF.Builder.CreateNot(alignmentMask));
834-
auto *objectAddr =
835-
IGF.emitByteOffsetGEP(ptr, startOffset, IGM.Int8Ty);
836-
IGF.Builder.CreateRet(objectAddr);
837-
});
838-
}
839-
840751
/// Find a witness to the fact that a type is a value type.
841752
/// Always adds an i8*.
842753
static void addValueWitness(IRGenModule &IGM,
@@ -870,17 +781,6 @@ static void addValueWitness(IRGenModule &IGM,
870781
}
871782
goto standard;
872783

873-
case ValueWitness::InitializeBufferWithTakeOfBuffer:
874-
if (packing == FixedPacking::Allocate) {
875-
return addFunction(getCopyOutOfLineBoxPointerFunction(
876-
IGM, cast<FixedTypeInfo>(concreteTI)));
877-
} else
878-
if (packing == FixedPacking::OffsetZero &&
879-
concreteTI.isBitwiseTakable(ResilienceExpansion::Maximal)) {
880-
return addFunction(getMemCpyFunction(IGM, concreteTI));
881-
}
882-
goto standard;
883-
884784
case ValueWitness::InitializeWithTake:
885785
if (concreteTI.isBitwiseTakable(ResilienceExpansion::Maximal)) {
886786
return addFunction(getMemCpyFunction(IGM, concreteTI));

lib/IRGen/IRGenMangler.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ std::string IRGenMangler::mangleValueWitness(Type type, ValueWitness witness) {
4545
GET_MANGLING(AssignWithCopy) \
4646
GET_MANGLING(InitializeWithTake) \
4747
GET_MANGLING(AssignWithTake) \
48-
GET_MANGLING(InitializeBufferWithTakeOfBuffer) \
4948
GET_MANGLING(GetEnumTagSinglePayload) \
5049
GET_MANGLING(StoreEnumTagSinglePayload) \
5150
GET_MANGLING(StoreExtraInhabitant) \

lib/IRGen/ResilientTypeInfo.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,6 @@ class ResilientTypeInfo : public WitnessSizedTypeInfo<Impl> {
8888
return this->getAddressForPointer(addr);
8989
}
9090

91-
Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
92-
Address dest, Address src,
93-
SILType T) const override {
94-
auto addr = emitInitializeBufferWithTakeOfBufferCall(IGF, T, dest, src);
95-
return this->getAddressForPointer(addr);
96-
}
97-
9891
void initializeWithCopy(IRGenFunction &IGF, Address dest, Address src,
9992
SILType T, bool isOutlined) const override {
10093
emitInitializeWithCopyCall(IGF, T, dest, src);

lib/IRGen/TypeInfo.h

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -370,23 +370,6 @@ class TypeInfo {
370370
Address srcBuffer,
371371
SILType T) const;
372372

373-
/// Perform a take-initialization from the given fixed-size buffer
374-
/// into an uninitialized fixed-size buffer, allocating the buffer if
375-
/// necessary and deallocating the destination buffer. Returns the
376-
/// address of the value inside the destination buffer.
377-
///
378-
/// This is equivalent to:
379-
/// auto srcAddress = projectBuffer(IGF, srcBuffer, T);
380-
/// initializeBufferWithTake(IGF, destBuffer, srcAddress, T);
381-
/// deallocateBuffer(IGF, srcBuffer, T);
382-
/// but may be able to re-use the buffer from the source buffer, and may
383-
/// be more efficient for dynamic types, since it uses a single
384-
/// value witness call.
385-
virtual Address initializeBufferWithTakeOfBuffer(IRGenFunction &IGF,
386-
Address destBuffer,
387-
Address srcBuffer,
388-
SILType T) const;
389-
390373
/// Take-initialize an address from a parameter explosion.
391374
virtual void initializeFromParams(IRGenFunction &IGF, Explosion &params,
392375
Address src, SILType T,

stdlib/public/runtime/ExistentialMetadataImpl.h

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,9 @@ struct LLVM_LIBRARY_VISIBILITY OpaqueExistentialBoxBase
107107
static Container *initializeWithTake(Container *dest, Container *src,
108108
A... args) {
109109
src->copyTypeInto(dest, args...);
110-
auto *type = src->getType();
111-
auto *vwt = type->getValueWitnesses();
112-
113-
if (vwt->isValueInline()) {
114-
auto *destValue =
115-
reinterpret_cast<OpaqueValue *>(dest->getBuffer(args...));
116-
auto *srcValue =
117-
reinterpret_cast<OpaqueValue *>(src->getBuffer(args...));
118-
119-
type->vw_initializeWithTake(destValue, srcValue);
120-
} else {
121-
// initWithTake of the reference to the cow box.
122-
copyReference(dest, src, Dest::Init, Source::Take, args...);
123-
}
110+
auto from = src->getBuffer(args...);
111+
auto to = dest->getBuffer(args...);
112+
memcpy(to, from, sizeof(ValueBuffer));
124113
return dest;
125114
}
126115

0 commit comments

Comments
 (0)