Skip to content

Commit f689af1

Browse files
Merge pull request #16775 from aschwaighofer/remove_initBufferWithTake
IRGen: Remove initializeBufferWithTakeOfBuffer in favor of memcpy
2 parents e27af10 + c6230c2 commit f689af1

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)