Skip to content

Commit 78a5b68

Browse files
committed
[embedded] Emit array builtins (copy, take, assign) as loops to avoid runtime calls
1 parent ad7f98a commit 78a5b68

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed

lib/IRGen/GenBuiltin.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,81 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
11281128
llvm::Value *dest = args.claimNext();
11291129
llvm::Value *src = args.claimNext();
11301130
llvm::Value *count = args.claimNext();
1131-
1131+
1132+
if (IGF.IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
1133+
auto tyPair = getLoweredTypeAndTypeInfo(
1134+
IGF.IGM, substitutions.getReplacementTypes()[0]);
1135+
SILType elemTy = tyPair.first;
1136+
const TypeInfo &elemTI = tyPair.second;
1137+
1138+
llvm::Value *firstSrcElem = IGF.Builder.CreateBitCast(
1139+
src, elemTI.getStorageType()->getPointerTo());
1140+
llvm::Value *firstDestElem = IGF.Builder.CreateBitCast(
1141+
dest, elemTI.getStorageType()->getPointerTo());
1142+
1143+
auto *origBB = IGF.Builder.GetInsertBlock();
1144+
auto *headerBB = IGF.createBasicBlock("loop_header");
1145+
auto *loopBB = IGF.createBasicBlock("loop_body");
1146+
auto *exitBB = IGF.createBasicBlock("loop_exit");
1147+
IGF.Builder.CreateBr(headerBB);
1148+
IGF.Builder.emitBlock(headerBB);
1149+
auto *phi = IGF.Builder.CreatePHI(count->getType(), 2);
1150+
phi->addIncoming(llvm::ConstantInt::get(count->getType(), 0), origBB);
1151+
llvm::Value *cmp = IGF.Builder.CreateICmpSLT(phi, count);
1152+
IGF.Builder.CreateCondBr(cmp, loopBB, exitBB);
1153+
1154+
IGF.Builder.emitBlock(loopBB);
1155+
llvm::Value *idx = phi;
1156+
1157+
switch (Builtin.ID) {
1158+
case BuiltinValueKind::TakeArrayBackToFront:
1159+
case BuiltinValueKind::AssignCopyArrayBackToFront: {
1160+
llvm::Value *countMinusIdx = IGF.Builder.CreateSub(count, phi);
1161+
auto *one = llvm::ConstantInt::get(count->getType(), 1);
1162+
idx = IGF.Builder.CreateSub(countMinusIdx, one);
1163+
break;
1164+
}
1165+
default:
1166+
break;
1167+
}
1168+
1169+
auto *srcElem = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
1170+
firstSrcElem, idx);
1171+
auto *destElem = IGF.Builder.CreateInBoundsGEP(elemTI.getStorageType(),
1172+
firstDestElem, idx);
1173+
Address destAddr = elemTI.getAddressForPointer(destElem);
1174+
Address srcAddr = elemTI.getAddressForPointer(srcElem);
1175+
1176+
bool isOutlined = false;
1177+
switch (Builtin.ID) {
1178+
case BuiltinValueKind::CopyArray:
1179+
elemTI.initializeWithCopy(IGF, destAddr, srcAddr, elemTy, isOutlined);
1180+
break;
1181+
case BuiltinValueKind::TakeArrayNoAlias:
1182+
case BuiltinValueKind::TakeArrayFrontToBack:
1183+
case BuiltinValueKind::TakeArrayBackToFront:
1184+
elemTI.initializeWithTake(IGF, destAddr, srcAddr, elemTy, isOutlined);
1185+
break;
1186+
case BuiltinValueKind::AssignCopyArrayNoAlias:
1187+
case BuiltinValueKind::AssignCopyArrayFrontToBack:
1188+
case BuiltinValueKind::AssignCopyArrayBackToFront:
1189+
elemTI.assignWithCopy(IGF, destAddr, srcAddr, elemTy, isOutlined);
1190+
break;
1191+
case BuiltinValueKind::AssignTakeArray:
1192+
elemTI.assignWithTake(IGF, destAddr, srcAddr, elemTy, isOutlined);
1193+
break;
1194+
default:
1195+
llvm_unreachable("out of sync with if condition");
1196+
}
1197+
auto *one = llvm::ConstantInt::get(count->getType(), 1);
1198+
auto *addIdx = IGF.Builder.CreateAdd(phi, one);
1199+
phi->addIncoming(addIdx, loopBB);
1200+
IGF.Builder.CreateBr(headerBB);
1201+
1202+
IGF.Builder.emitBlock(exitBB);
1203+
return;
1204+
}
1205+
11321206
auto valueTy = getLoweredTypeAndTypeInfo(IGF.IGM,
11331207
substitutions.getReplacementTypes()[0]);
11341208

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-swift-emit-ir %s -parse-stdlib -module-name Swift -enable-experimental-feature Embedded -target arm64e-apple-none | %FileCheck %s
2+
3+
class MyClass {}
4+
5+
struct MyStruct {
6+
var c: MyClass
7+
}
8+
9+
public func foo(x: Builtin.RawPointer, y: Builtin.RawPointer, count: Builtin.Word) {
10+
Builtin.copyArray(MyStruct.self, x, y, count)
11+
Builtin.copyArray(MyStruct.self, x, y, count)
12+
Builtin.takeArrayNoAlias(MyStruct.self, x, y, count)
13+
Builtin.takeArrayFrontToBack(MyStruct.self, x, y, count)
14+
Builtin.takeArrayBackToFront(MyStruct.self, x, y, count)
15+
Builtin.assignCopyArrayNoAlias(MyStruct.self, x, y, count)
16+
Builtin.assignCopyArrayFrontToBack(MyStruct.self, x, y, count)
17+
Builtin.assignCopyArrayBackToFront(MyStruct.self, x, y, count)
18+
Builtin.assignTakeArray(MyStruct.self, x, y, count)
19+
}
20+
21+
// No runtime calls should be present.
22+
// CHECK-NOT: @swift_arrayInitWithCopy
23+
// CHECK-NOT: @swift_arrayAssignWithCopyNoAlias
24+
// CHECK-NOT: @swift_arrayAssignWithCopyFrontToBack
25+
// CHECK-NOT: @swift_arrayAssignWithCopyBackToFront
26+
// CHECK-NOT: @swift_arrayAssignWithTake

0 commit comments

Comments
 (0)