-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathpack_stack_metadata_alloc_loop.sil
82 lines (73 loc) · 4.35 KB
/
pack_stack_metadata_alloc_loop.sil
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// RUN: %target-run-simple-swift(-parse-sil -Xfrontend -enable-pack-metadata-stack-promotion=true)
// RUN: %target-swift-frontend -parse-sil -enable-pack-metadata-stack-promotion=true -emit-ir -primary-file %s | %IRGenFileCheck %s
// REQUIRES: executable_test
// REQUIRES: CPU=arm64
// Allocate metadata packs on the stack in a loop. If these packs weren't
// deallocated, the stack would be exhausted.
import Builtin
import Swift
struct S {}
sil [ossa] @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
%looper = function_ref @looper : $@convention(thin) <each T_1, each T_2> () -> ()
apply %looper<Pack{S, S, S}, Pack{S, S}>() : $@convention(thin) <each T_1, each T_2> () -> ()
// If the stack were exhausted while looping, the apply of %looper would crash
// and execution would never reach this point.
%out_literal = integer_literal $Builtin.Int32, 0
%out = struct $Int32 (%out_literal : $Builtin.Int32)
return %out : $Int32
}
sil @callee : $@convention(thin) <each T> () -> () {
%retval = tuple ()
return %retval : $()
}
// CHECK-LABEL: define {{.*}}@looper(
// CHECK-SAME: [[INT]] %0, [[INT]] %1, ptr %"each T_1", ptr %"each T_2") {{.*}} {
// CHECK: [[ENTRY:entry]]:
// CHECK: br label %[[HEADER:[^,]+]]
// CHECK: [[HEADER]]:
// CHECK: [[PREVIOUS:%[^,]+]] = phi i64 [ 10000000, %[[ENTRY]] ], [ [[REMAINING:%[^,]+]], %{{[^,]+}} ]
// CHECK: [[COMBINED_PACK_SIZE:%[^,]+]] = add [[INT]] %0, %1
// CHECK: [[STACK_BEFORE_FIRST_ALLOCA:%[^,]+]] = call ptr @llvm.stacksave.p0()
// CHECK: [[FIRST_ALLOCA_METADATA_PACK:%[^,]+]] = alloca ptr, [[INT]] [[COMBINED_PACK_SIZE]]
// CHECK: call swiftcc void @callee([[INT]] [[COMBINED_PACK_SIZE]], ptr [[FIRST_ALLOCA_METADATA_PACK]])
// CHECK: [[COMBINED_PACK_SIZE_2:%[^,]+]] = add [[INT]] %1, %0
// CHECK: [[STACK_BEFORE_SECOND_ALLOCA:%[^,]+]] = call ptr @llvm.stacksave.p0()
// CHECK: [[SECOND_ALLOCA_METADATA_PACK:%[^,]+]] = alloca ptr, [[INT]] [[COMBINED_PACK_SIZE_2]]
// CHECK: call swiftcc void @callee([[INT]] [[COMBINED_PACK_SIZE_2]], ptr [[SECOND_ALLOCA_METADATA_PACK]])
// CHECK: [[REMAINING_AND_OVERFLOW:%[^,]+]] = call { i64, i1 } @llvm.ssub.with.overflow.i64(i64 [[PREVIOUS]], i64 1)
// CHECK: [[REMAINING]] = extractvalue { i64, i1 } [[REMAINING_AND_OVERFLOW]], 0
// CHECK: [[IS_ZERO:%[^,]+]] = icmp eq i64 [[REMAINING]], 0
// CHECK: br i1 [[IS_ZERO]], label %[[EXIT:[^,]+]], label %[[BACKEDGE:[^,]+]]
// CHECK: [[BACKEDGE]]:
// CHECK: call void @llvm.stackrestore.p0(ptr [[STACK_BEFORE_SECOND_ALLOCA]])
// CHECK: call void @llvm.stackrestore.p0(ptr [[STACK_BEFORE_FIRST_ALLOCA]])
// CHECK: br label %[[HEADER]]
// CHECK: [[EXIT]]:
// CHECK: [[STACK_BEFORE_SECOND_ALLOCAlcssa:%.*]] = phi ptr [ [[STACK_BEFORE_SECOND_ALLOCA]], %{{.*}} ]
// CHECK: [[STACK_BEFORE_FIRST_ALLOCAlcssa:%.*]] = phi ptr [ [[STACK_BEFORE_FIRST_ALLOCA]], %{{.*}} ]
// CHECK: call void @llvm.stackrestore.p0(ptr [[STACK_BEFORE_SECOND_ALLOCAlcssa]])
// CHECK: call void @llvm.stackrestore.p0(ptr [[STACK_BEFORE_FIRST_ALLOCAlcssa]])
// CHECK: ret void
// CHECK: }
sil @looper : $@convention(thin) <each T_1, each T_2> () -> () {
entry:
%callee = function_ref @callee : $@convention(thin) <each T> () -> ()
%initial = integer_literal $Builtin.Int64, 10000000
br header(%initial : $Builtin.Int64)
header(%previous : $Builtin.Int64):
apply %callee<Pack{repeat each T_1, repeat each T_2}>() : $@convention(thin) <each T> () -> ()
apply %callee<Pack{repeat each T_2, repeat each T_1}>() : $@convention(thin) <each T> () -> ()
%offset = integer_literal $Builtin.Int64, 1
%flag = integer_literal $Builtin.Int1, -1
%remainingAndOverflow = builtin "ssub_with_overflow_Int64"(%previous : $Builtin.Int64, %offset : $Builtin.Int64, %flag : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1)
%remaining = tuple_extract %remainingAndOverflow : $(Builtin.Int64, Builtin.Int1), 0
%zero = integer_literal $Builtin.Int64, 0
%isZero = builtin "cmp_eq_Int64"(%remaining : $Builtin.Int64, %zero : $Builtin.Int64) : $Builtin.Int1
cond_br %isZero, exit, backedge
backedge:
br header(%remaining : $Builtin.Int64)
exit:
%retval = tuple ()
return %retval : $()
}