Skip to content

Commit 19557cd

Browse files
Merge pull request swiftlang#74304 from aschwaighofer/use_static_alloca_for_stackAlloc
IRGen: Use static alloca for builtin stackAlloc when possible
2 parents 9659601 + 89b6f91 commit 19557cd

File tree

5 files changed

+35
-12
lines changed

5 files changed

+35
-12
lines changed

lib/IRGen/GenOpaque.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,14 @@ void IRGenFunction::emitDeallocateDynamicAlloca(StackAddress address,
656656
// NOTE: llvm does not support dynamic allocas in coroutines.
657657

658658
auto allocToken = address.getExtraInfo();
659-
assert(allocToken && "dynamic alloca in coroutine without alloc token?");
659+
if (!allocToken) {
660+
#ifndef NDEBUG
661+
auto *alloca = cast<llvm::AllocaInst>(address.getAddress().getAddress());
662+
assert(isa<llvm::ConstantInt>(alloca->getArraySize()) &&
663+
"Dynamic alloca without a token?!");
664+
#endif
665+
return;
666+
}
660667
Builder.CreateIntrinsicCall(llvm::Intrinsic::coro_alloca_free, allocToken);
661668
return;
662669
}

lib/IRGen/IRGenSIL.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3559,6 +3559,11 @@ static llvm::Value *getStackAllocationSize(IRGenSILFunction &IGF,
35593559
result = IGF.Builder.CreateMul(capacity, stride);
35603560
}
35613561

3562+
if (auto constResult = dyn_cast<llvm::ConstantInt>(result)) {
3563+
if (!constResult->getUniqueInteger().isZero())
3564+
return constResult;
3565+
}
3566+
35623567
// If the caller requests a zero-byte allocation, allocate one byte instead
35633568
// to ensure that the resulting pointer is valid and unique on the stack.
35643569
return IGF.Builder.CreateIntrinsicCall(llvm::Intrinsic::umax,
@@ -3601,6 +3606,14 @@ static void emitBuiltinStackAlloc(IRGenSILFunction &IGF,
36013606
IGF, i->getOperand(0), i->getOperand(1), loc);
36023607
auto align = getStackAllocationAlignment(IGF, i->getOperand(2), loc);
36033608

3609+
// Emit a static alloca if the size is constant.
3610+
if (auto *constSize = dyn_cast<llvm::ConstantInt>(size)) {
3611+
auto stackAddress = IGF.createAlloca(IGF.IGM.Int8Ty, constSize, align,
3612+
"temp_alloc");
3613+
IGF.setLoweredStackAddress(i, {stackAddress});
3614+
return;
3615+
}
3616+
36043617
auto stackAddress = IGF.emitDynamicAlloca(IGF.IGM.Int8Ty, size, align,
36053618
false, "temp_alloc");
36063619
IGF.setLoweredStackAddress(i, stackAddress);

test/IRGen/temporary_allocation/async.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ func f() async {
99
blackHole(buffer.baseAddress)
1010
}
1111
}
12-
// CHECK: alloca [123 x i8], align 1
12+
1313
// CHECK-NOT: swift_task_alloc

test/IRGen/temporary_allocation/codegen.swift

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,20 @@ do {
1010
blackHole(ptr)
1111
ptr.deallocate()
1212
}
13-
// CHECK: ptrtoint ptr {{.*}} to [[WORD:i[0-9]+]]
1413

1514
// MARK: Trivial Cases
1615

16+
// CHECK: [[ONE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca i8, align 1
17+
// CHECK: [[FIVE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca [5 x i8], align 1
18+
// CHECK: [[ONE_KB_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 8
19+
// CHECK: [[ONE_KB_RAND_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 16
20+
// CHECK: [[INT_PTR_RAW:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4
21+
// CHECK: [[INT_PTR_RAW2:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4
22+
// CHECK: [[VOID_PTR_RAW:%temp_alloc[0-9]*]] = alloca [2 x i8], align 1
23+
24+
// CHECK: ptrtoint ptr {{.*}} to [[WORD:i[0-9]+]]
25+
26+
1727
withUnsafeTemporaryAllocation(byteCount: 0, alignment: 1) { buffer in
1828
blackHole(buffer.baseAddress)
1929
}
@@ -24,21 +34,18 @@ withUnsafeTemporaryAllocation(byteCount: 0, alignment: 1) { buffer in
2434
withUnsafeTemporaryAllocation(byteCount: 1, alignment: 1) { buffer in
2535
blackHole(buffer.baseAddress)
2636
}
27-
// CHECK: [[ONE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca i8, align 1
2837
// CHECK: [[ONE_BYTE_PTR:%[0-9]+]] = ptrtoint ptr [[ONE_BYTE_PTR_RAW]] to [[WORD]]
2938
// CHECK: call swiftcc void @blackHole([[WORD]] [[ONE_BYTE_PTR]])
3039

3140
withUnsafeTemporaryAllocation(byteCount: 5, alignment: 1) { buffer in
3241
blackHole(buffer.baseAddress)
3342
}
34-
// CHECK: [[FIVE_BYTE_PTR_RAW:%temp_alloc[0-9]*]] = alloca [5 x i8], align 1
3543
// CHECK: [[FIVE_BYTE_PTR:%[0-9]+]] = ptrtoint ptr [[FIVE_BYTE_PTR_RAW]] to [[WORD]]
3644
// CHECK: call swiftcc void @blackHole([[WORD]] [[FIVE_BYTE_PTR]])
3745

3846
withUnsafeTemporaryAllocation(byteCount: 1024, alignment: 8) { buffer in
3947
blackHole(buffer.baseAddress)
4048
}
41-
// CHECK: [[ONE_KB_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 8
4249
// CHECK: [[ONE_KB_PTR:%[0-9]+]] = ptrtoint ptr [[ONE_KB_PTR_RAW]] to [[WORD]]
4350
// CHECK: call swiftcc void @blackHole([[WORD]] [[ONE_KB_PTR]])
4451

@@ -47,7 +54,6 @@ withUnsafeTemporaryAllocation(byteCount: 1024, alignment: 8) { buffer in
4754
withUnsafeTemporaryAllocation(byteCount: 1024, alignment: Int.random(in: 0 ..< 16)) { buffer in
4855
blackHole(buffer.baseAddress)
4956
}
50-
// CHECK: [[ONE_KB_RAND_PTR_RAW:%temp_alloc[0-9]*]] = alloca [1024 x i8], align 16
5157
// CHECK: [[ONE_KB_RAND_PTR:%[0-9]+]] = ptrtoint ptr [[ONE_KB_RAND_PTR_RAW]] to [[WORD]]
5258
// CHECK: call swiftcc void @blackHole([[WORD]] [[ONE_KB_RAND_PTR]])
5359

@@ -56,21 +62,18 @@ withUnsafeTemporaryAllocation(byteCount: 1024, alignment: Int.random(in: 0 ..< 1
5662
withUnsafeTemporaryAllocation(of: Int32.self, capacity: 4) { buffer in
5763
blackHole(buffer.baseAddress)
5864
}
59-
// CHECK: [[INT_PTR_RAW:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4
6065
// CHECK: [[INT_PTR:%[0-9]+]] = ptrtoint ptr [[INT_PTR_RAW]] to [[WORD]]
6166
// CHECK: call swiftcc void @blackHole([[WORD]] [[INT_PTR]])
6267

6368
_withUnprotectedUnsafeTemporaryAllocation(of: Int32.self, capacity: 4) { buffer in
6469
blackHole(buffer.baseAddress)
6570
}
66-
// CHECK: [[INT_PTR_RAW:%temp_alloc[0-9]*]] = alloca [16 x i8], align 4
67-
// CHECK: [[INT_PTR:%[0-9]+]] = ptrtoint ptr [[INT_PTR_RAW]] to [[WORD]]
71+
// CHECK: [[INT_PTR:%[0-9]+]] = ptrtoint ptr [[INT_PTR_RAW2]] to [[WORD]]
6872
// CHECK: call swiftcc void @blackHole([[WORD]] [[INT_PTR]])
6973

7074
withUnsafeTemporaryAllocation(of: Void.self, capacity: 2) { buffer in
7175
blackHole(buffer.baseAddress)
7276
}
73-
// CHECK: [[VOID_PTR_RAW:%temp_alloc[0-9]*]] = alloca [2 x i8], align 1
7477
// CHECK: [[VOID_PTR:%[0-9]+]] = ptrtoint ptr [[VOID_PTR_RAW]] to [[WORD]]
7578
// CHECK: call swiftcc void @blackHole([[WORD]] [[VOID_PTR]])
7679

test/IRGen/temporary_allocation/codegen_very_large_allocation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ withUnsafeTemporaryAllocation(byteCount: 0x0FFF_FFFF, alignment: 1) { buffer in
2424
// CHECK-LARGE-HEAP-ALLOC-NEXT: {{(tail )?}}call void @swift_slowDealloc(ptr [[HEAP_PTR_RAW]], [[WORD]] -1, [[WORD]] -1)
2525

2626
// CHECK-LARGE-STACK-ALLOC: [[STACK_PTR_RAW:%temp_alloc[0-9]*]] = alloca [268435455 x i8], align 1
27-
// CHECK-LARGE-STACK-ALLOC-NEXT: [[STACK_PTR:%[0-9]+]] = ptrtoint ptr [[STACK_PTR_RAW]] to [[WORD]]
27+
// CHECK-LARGE-STACK-ALLOC: [[STACK_PTR:%[0-9]+]] = ptrtoint ptr [[STACK_PTR_RAW]] to [[WORD]]
2828
// CHECK-LARGE-STACK-ALLOC-NEXT: call swiftcc void @blackHole([[WORD]] [[STACK_PTR]])
2929

3030
// CHECK-LARGE-ALLOC-DAG: [[IS_SAFE:%[0-9]+]] = {{(tail )?}}call {{(zeroext )?}}i1 @swift_stdlib_isStackAllocationSafe([[WORD]] 268435455, [[WORD]] 1)

0 commit comments

Comments
 (0)