Skip to content

Commit 7014fcf

Browse files
authored
Merge pull request #68543 from kubamracek/embedded-array-builtins3
[embedded] Runtime-call free array builtins
2 parents c6ce442 + 3e1fac0 commit 7014fcf

File tree

9 files changed

+316
-2
lines changed

9 files changed

+316
-2
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ extension BuiltinInst : OnoneSimplifyable {
3232
.Strideof,
3333
.Alignof:
3434
optimizeTargetTypeConst(context)
35+
case .DestroyArray,
36+
.CopyArray,
37+
.TakeArrayNoAlias,
38+
.TakeArrayFrontToBack,
39+
.TakeArrayBackToFront,
40+
.AssignCopyArrayNoAlias,
41+
.AssignCopyArrayFrontToBack,
42+
.AssignCopyArrayBackToFront,
43+
.AssignTakeArray:
44+
optimizeArrayBuiltin(context)
3545
default:
3646
if let literal = constantFold(context) {
3747
uses.replaceAll(with: literal, context)
@@ -162,6 +172,18 @@ private extension BuiltinInst {
162172
uses.replaceAll(with: literal, context)
163173
context.erase(instruction: self)
164174
}
175+
176+
func optimizeArrayBuiltin(_ context: SimplifyContext) {
177+
guard let metatypeInst = operands[0].value as? MetatypeInst,
178+
metatypeInst.type.representationOfMetatype(in: parentFunction) == .Thick else {
179+
return
180+
}
181+
182+
let instanceType = metatypeInst.type.instanceTypeOfMetatype(in: parentFunction)
183+
let builder = Builder(before: self, context)
184+
let metatype = builder.createMetatype(of: instanceType, representation: .Thin)
185+
operands[0].set(to: metatype, context)
186+
}
165187
}
166188

167189
private func hasSideEffectForBuiltinOnce(_ instruction: Instruction) -> Bool {

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,9 @@ public struct Builder {
309309
useConformancesOf.bridged)
310310
return notifyNew(initExistential.getAs(InitExistentialRefInst.self))
311311
}
312+
313+
public func createMetatype(of type: Type, representation: swift.MetatypeRepresentation) -> MetatypeInst {
314+
let metatype = bridged.createMetatype(type.bridged, representation)
315+
return notifyNew(metatype.getAs(MetatypeInst.self))
316+
}
312317
}

SwiftCompilerSources/Sources/SIL/Type.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
9090
bridged.getInstanceTypeOfMetatype(function.bridged.getFunction()).type
9191
}
9292

93+
public func representationOfMetatype(in function: Function) -> swift.MetatypeRepresentation {
94+
bridged.getRepresentationOfMetatype(function.bridged.getFunction())
95+
}
96+
9397
public var isCalleeConsumedFunction: Bool { bridged.isCalleeConsumedFunction() }
9498

9599
public var isMarkedAsImmortal: Bool { bridged.isMarkedAsImmortal() }

include/swift/SIL/SILBridging.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,13 @@ struct BridgedBuilder{
13571357
instance.getSILValue(),
13581358
src->getConformances())};
13591359
}
1360+
1361+
SWIFT_IMPORT_UNSAFE
1362+
BridgedInstruction createMetatype(swift::SILType type, swift::MetatypeRepresentation representation) const {
1363+
swift::MetatypeType *mt = swift::MetatypeType::get(type.getASTType(), representation);
1364+
swift::SILType t = swift::SILType::getPrimitiveObjectType(swift::CanType(mt));
1365+
return {builder().createMetatype(regularLoc(), t)};
1366+
}
13601367
};
13611368

13621369
// AST bridging

include/swift/SIL/SILType.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,8 @@ class SILType {
864864

865865
SILType getInstanceTypeOfMetatype(SILFunction *function) const;
866866

867+
MetatypeRepresentation getRepresentationOfMetatype(SILFunction *function) const;
868+
867869
bool isOrContainsObjectiveCClass() const;
868870

869871
bool isCalleeConsumedFunction() const {

lib/IRGen/GenBuiltin.cpp

Lines changed: 111 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,42 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
11051105

11061106
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
11071107
substitutions.getReplacementTypes()[0]);
1108-
1108+
1109+
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
1110+
SILType elemTy = valueTy.first;
1111+
const TypeInfo &elemTI = valueTy.second;
1112+
1113+
llvm::Value *firstElem = IGF.Builder.CreateBitCast(
1114+
ptr, elemTI.getStorageType()->getPointerTo());
1115+
1116+
auto *origBB = IGF.Builder.GetInsertBlock();
1117+
auto *headerBB = IGF.createBasicBlock("loop_header");
1118+
auto *loopBB = IGF.createBasicBlock("loop_body");
1119+
auto *exitBB = IGF.createBasicBlock("loop_exit");
1120+
IGF.Builder.CreateBr(headerBB);
1121+
IGF.Builder.emitBlock(headerBB);
1122+
auto *phi = IGF.Builder.CreatePHI(count->getType(), 2);
1123+
phi->addIncoming(llvm::ConstantInt::get(count->getType(), 0), origBB);
1124+
llvm::Value *cmp = IGF.Builder.CreateICmpSLT(phi, count);
1125+
IGF.Builder.CreateCondBr(cmp, loopBB, exitBB);
1126+
1127+
IGF.Builder.emitBlock(loopBB);
1128+
auto *addr = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
1129+
firstElem, phi);
1130+
1131+
bool isOutlined = false;
1132+
elemTI.destroy(IGF, elemTI.getAddressForPointer(addr), elemTy,
1133+
isOutlined);
1134+
1135+
auto *one = llvm::ConstantInt::get(count->getType(), 1);
1136+
auto *add = IGF.Builder.CreateAdd(phi, one);
1137+
phi->addIncoming(add, loopBB);
1138+
IGF.Builder.CreateBr(headerBB);
1139+
1140+
IGF.Builder.emitBlock(exitBB);
1141+
return;
1142+
}
1143+
11091144
ptr = IGF.Builder.CreateBitCast(ptr,
11101145
valueTy.second.getStorageType()->getPointerTo());
11111146
Address array = valueTy.second.getAddressForPointer(ptr);
@@ -1128,7 +1163,81 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
11281163
llvm::Value *dest = args.claimNext();
11291164
llvm::Value *src = args.claimNext();
11301165
llvm::Value *count = args.claimNext();
1131-
1166+
1167+
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
1168+
auto tyPair = getLoweredTypeAndTypeInfo(
1169+
IGF.IGM, substitutions.getReplacementTypes()[0]);
1170+
SILType elemTy = tyPair.first;
1171+
const TypeInfo &elemTI = tyPair.second;
1172+
1173+
llvm::Value *firstSrcElem = IGF.Builder.CreateBitCast(
1174+
src, elemTI.getStorageType()->getPointerTo());
1175+
llvm::Value *firstDestElem = IGF.Builder.CreateBitCast(
1176+
dest, elemTI.getStorageType()->getPointerTo());
1177+
1178+
auto *origBB = IGF.Builder.GetInsertBlock();
1179+
auto *headerBB = IGF.createBasicBlock("loop_header");
1180+
auto *loopBB = IGF.createBasicBlock("loop_body");
1181+
auto *exitBB = IGF.createBasicBlock("loop_exit");
1182+
IGF.Builder.CreateBr(headerBB);
1183+
IGF.Builder.emitBlock(headerBB);
1184+
auto *phi = IGF.Builder.CreatePHI(count->getType(), 2);
1185+
phi->addIncoming(llvm::ConstantInt::get(count->getType(), 0), origBB);
1186+
llvm::Value *cmp = IGF.Builder.CreateICmpSLT(phi, count);
1187+
IGF.Builder.CreateCondBr(cmp, loopBB, exitBB);
1188+
1189+
IGF.Builder.emitBlock(loopBB);
1190+
llvm::Value *idx = phi;
1191+
1192+
switch (Builtin.ID) {
1193+
case BuiltinValueKind::TakeArrayBackToFront:
1194+
case BuiltinValueKind::AssignCopyArrayBackToFront: {
1195+
llvm::Value *countMinusIdx = IGF.Builder.CreateSub(count, phi);
1196+
auto *one = llvm::ConstantInt::get(count->getType(), 1);
1197+
idx = IGF.Builder.CreateSub(countMinusIdx, one);
1198+
break;
1199+
}
1200+
default:
1201+
break;
1202+
}
1203+
1204+
auto *srcElem = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
1205+
firstSrcElem, idx);
1206+
auto *destElem = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
1207+
firstDestElem, idx);
1208+
Address destAddr = elemTI.getAddressForPointer(destElem);
1209+
Address srcAddr = elemTI.getAddressForPointer(srcElem);
1210+
1211+
bool isOutlined = false;
1212+
switch (Builtin.ID) {
1213+
case BuiltinValueKind::CopyArray:
1214+
elemTI.initializeWithCopy(IGF, destAddr, srcAddr, elemTy, isOutlined);
1215+
break;
1216+
case BuiltinValueKind::TakeArrayNoAlias:
1217+
case BuiltinValueKind::TakeArrayFrontToBack:
1218+
case BuiltinValueKind::TakeArrayBackToFront:
1219+
elemTI.initializeWithTake(IGF, destAddr, srcAddr, elemTy, isOutlined);
1220+
break;
1221+
case BuiltinValueKind::AssignCopyArrayNoAlias:
1222+
case BuiltinValueKind::AssignCopyArrayFrontToBack:
1223+
case BuiltinValueKind::AssignCopyArrayBackToFront:
1224+
elemTI.assignWithCopy(IGF, destAddr, srcAddr, elemTy, isOutlined);
1225+
break;
1226+
case BuiltinValueKind::AssignTakeArray:
1227+
elemTI.assignWithTake(IGF, destAddr, srcAddr, elemTy, isOutlined);
1228+
break;
1229+
default:
1230+
llvm_unreachable("out of sync with if condition");
1231+
}
1232+
auto *one = llvm::ConstantInt::get(count->getType(), 1);
1233+
auto *addIdx = IGF.Builder.CreateAdd(phi, one);
1234+
phi->addIncoming(addIdx, loopBB);
1235+
IGF.Builder.CreateBr(headerBB);
1236+
1237+
IGF.Builder.emitBlock(exitBB);
1238+
return;
1239+
}
1240+
11321241
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
11331242
substitutions.getReplacementTypes()[0]);
11341243

lib/SIL/IR/SILType.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,11 @@ SILType SILType::getInstanceTypeOfMetatype(SILFunction *function) const {
10761076
return tl.getLoweredType();
10771077
}
10781078

1079+
MetatypeRepresentation SILType::getRepresentationOfMetatype(SILFunction *function) const {
1080+
auto metaType = castTo<MetatypeType>();
1081+
return metaType->getRepresentation();
1082+
}
1083+
10791084
bool SILType::isOrContainsObjectiveCClass() const {
10801085
return getASTType().findIf([](Type ty) {
10811086
if (ClassDecl *cd = ty->getClassOrBoundGenericClass()) {

test/SILOptimizer/simplify_builtin.sil

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,3 +383,110 @@ bb0:
383383
return %4 : $Int8
384384
}
385385

386+
// CHECK-LABEL: sil @convert_thick_to_thin1
387+
// CHECK-NOT: metatype $@thick C1<Int>.Type
388+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
389+
// CHECK: [[R:%.*]] = builtin "copyArray"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
390+
// CHECK: return %0 : $Builtin.RawPointer
391+
sil @convert_thick_to_thin1 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
392+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
393+
%2 = metatype $@thick C1<Int>.Type
394+
%3 = builtin "copyArray"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
395+
return %0 : $Builtin.RawPointer
396+
}
397+
398+
// CHECK-LABEL: sil @convert_thick_to_thin2
399+
// CHECK-NOT: metatype $@thick C1<Int>.Type
400+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
401+
// CHECK: [[R:%.*]] = builtin "takeArrayNoAlias"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
402+
// CHECK: return %0 : $Builtin.RawPointer
403+
sil @convert_thick_to_thin2 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
404+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
405+
%2 = metatype $@thick C1<Int>.Type
406+
%3 = builtin "takeArrayNoAlias"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
407+
return %0 : $Builtin.RawPointer
408+
}
409+
410+
// CHECK-LABEL: sil @convert_thick_to_thin3
411+
// CHECK-NOT: metatype $@thick C1<Int>.Type
412+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
413+
// CHECK: [[R:%.*]] = builtin "takeArrayFrontToBack"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
414+
// CHECK: return %0 : $Builtin.RawPointer
415+
sil @convert_thick_to_thin3 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
416+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
417+
%2 = metatype $@thick C1<Int>.Type
418+
%3 = builtin "takeArrayFrontToBack"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
419+
return %0 : $Builtin.RawPointer
420+
}
421+
422+
// CHECK-LABEL: sil @convert_thick_to_thin4
423+
// CHECK-NOT: metatype $@thick C1<Int>.Type
424+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
425+
// CHECK: [[R:%.*]] = builtin "takeArrayBackToFront"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
426+
// CHECK: return %0 : $Builtin.RawPointer
427+
sil @convert_thick_to_thin4 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
428+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
429+
%2 = metatype $@thick C1<Int>.Type
430+
%3 = builtin "takeArrayBackToFront"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
431+
return %0 : $Builtin.RawPointer
432+
}
433+
434+
// CHECK-LABEL: sil @convert_thick_to_thin5
435+
// CHECK-NOT: metatype $@thick C1<Int>.Type
436+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
437+
// CHECK: [[R:%.*]] = builtin "assignCopyArrayNoAlias"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
438+
// CHECK: return %0 : $Builtin.RawPointer
439+
sil @convert_thick_to_thin5 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
440+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
441+
%2 = metatype $@thick C1<Int>.Type
442+
%3 = builtin "assignCopyArrayNoAlias"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
443+
return %0 : $Builtin.RawPointer
444+
}
445+
446+
// CHECK-LABEL: sil @convert_thick_to_thin6
447+
// CHECK-NOT: metatype $@thick C1<Int>.Type
448+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
449+
// CHECK: [[R:%.*]] = builtin "assignCopyArrayFrontToBack"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
450+
// CHECK: return %0 : $Builtin.RawPointer
451+
sil @convert_thick_to_thin6 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
452+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
453+
%2 = metatype $@thick C1<Int>.Type
454+
%3 = builtin "assignCopyArrayFrontToBack"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
455+
return %0 : $Builtin.RawPointer
456+
}
457+
458+
// CHECK-LABEL: sil @convert_thick_to_thin7
459+
// CHECK-NOT: metatype $@thick C1<Int>.Type
460+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
461+
// CHECK: [[R:%.*]] = builtin "assignCopyArrayBackToFront"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
462+
// CHECK: return %0 : $Builtin.RawPointer
463+
sil @convert_thick_to_thin7 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
464+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
465+
%2 = metatype $@thick C1<Int>.Type
466+
%3 = builtin "assignCopyArrayBackToFront"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
467+
return %0 : $Builtin.RawPointer
468+
}
469+
470+
// CHECK-LABEL: sil @convert_thick_to_thin8
471+
// CHECK-NOT: metatype $@thick C1<Int>.Type
472+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
473+
// CHECK: [[R:%.*]] = builtin "assignTakeArray"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
474+
// CHECK: return %0 : $Builtin.RawPointer
475+
sil @convert_thick_to_thin8 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
476+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
477+
%2 = metatype $@thick C1<Int>.Type
478+
%3 = builtin "assignTakeArray"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
479+
return %0 : $Builtin.RawPointer
480+
}
481+
482+
// CHECK-LABEL: sil @convert_thick_to_thin9
483+
// CHECK-NOT: metatype $@thick C1<Int>.Type
484+
// CHECK: [[L:%.*]] = metatype $@thin C1<Int>.Type
485+
// CHECK: [[R:%.*]] = builtin "destroyArray"<C1<Int>>([[L:%.*]] : $@thin C1<Int>.Type, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
486+
// CHECK: return %0 : $Builtin.RawPointer
487+
sil @convert_thick_to_thin9 : $@convention(thin) (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer {
488+
bb0(%0 : $Builtin.RawPointer, %1 : $Builtin.Word):
489+
%2 = metatype $@thick C1<Int>.Type
490+
%3 = builtin "destroyArray"<C1<Int>>(%2 : $@thick C1<Int>.Type, %0 : $Builtin.RawPointer, %1 : $Builtin.Word) : $()
491+
return %0 : $Builtin.RawPointer
492+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %target-swift-emit-ir %s -parse-stdlib -module-name Swift -enable-experimental-feature Embedded -wmo -target arm64e-apple-none | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
5+
// TODO: these builtins in embedded Swift have a completely different IRGen, we need executable tests for them.
6+
7+
class MyClass {}
8+
9+
struct MyStruct {
10+
var c: MyClass
11+
}
12+
13+
public func foo(x: Builtin.RawPointer, y: Builtin.RawPointer, count: Builtin.Word) {
14+
Builtin.copyArray(MyStruct.self, x, y, count)
15+
Builtin.takeArrayNoAlias(MyStruct.self, x, y, count)
16+
Builtin.takeArrayFrontToBack(MyStruct.self, x, y, count)
17+
Builtin.takeArrayBackToFront(MyStruct.self, x, y, count)
18+
Builtin.assignCopyArrayNoAlias(MyStruct.self, x, y, count)
19+
Builtin.assignCopyArrayFrontToBack(MyStruct.self, x, y, count)
20+
Builtin.assignCopyArrayBackToFront(MyStruct.self, x, y, count)
21+
Builtin.assignTakeArray(MyStruct.self, x, y, count)
22+
Builtin.destroyArray(MyStruct.self, x, count)
23+
}
24+
25+
public func bar(x: Builtin.RawPointer, y: Builtin.RawPointer, count: Builtin.Word) {
26+
var s = MyGenericStruct<MyStruct>()
27+
s.foo(x: x, y: y, count: count)
28+
}
29+
30+
public struct MyGenericStruct<T> {
31+
public func foo(x: Builtin.RawPointer, y: Builtin.RawPointer, count: Builtin.Word) {
32+
Builtin.copyArray(T.self, x, y, count)
33+
Builtin.takeArrayNoAlias(T.self, x, y, count)
34+
Builtin.takeArrayFrontToBack(T.self, x, y, count)
35+
Builtin.takeArrayBackToFront(T.self, x, y, count)
36+
Builtin.assignCopyArrayNoAlias(T.self, x, y, count)
37+
Builtin.assignCopyArrayFrontToBack(T.self, x, y, count)
38+
Builtin.assignCopyArrayBackToFront(T.self, x, y, count)
39+
Builtin.assignTakeArray(T.self, x, y, count)
40+
Builtin.destroyArray(T.self, x, count)
41+
}
42+
}
43+
44+
// No runtime calls should be present.
45+
// CHECK-NOT: @swift_arrayInitWithCopy
46+
// CHECK-NOT: @swift_arrayInitWithTakeNoAlias
47+
// CHECK-NOT: @swift_arrayInitWithTakeFrontToBack
48+
// CHECK-NOT: @swift_arrayInitWithTakeBackToFront
49+
// CHECK-NOT: @swift_arrayAssignWithCopyNoAlias
50+
// CHECK-NOT: @swift_arrayAssignWithCopyFrontToBack
51+
// CHECK-NOT: @swift_arrayAssignWithCopyBackToFront
52+
// CHECK-NOT: @swift_arrayAssignWithTake
53+
// CHECK-NOT: @swift_arrayDestroy

0 commit comments

Comments
 (0)