File: pack_stack_metadata_alloc_loop.sil

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (79 lines) | stat: -rw-r--r-- 4,185 bytes parent folder | download
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
// 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

// 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()
// 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()
// 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(ptr [[STACK_BEFORE_SECOND_ALLOCA]])
// CHECK:         call void @llvm.stackrestore(ptr [[STACK_BEFORE_FIRST_ALLOCA]])
// CHECK:         br label %[[HEADER]]
// CHECK:       [[EXIT]]:
// CHECK:         call void @llvm.stackrestore(ptr [[STACK_BEFORE_SECOND_ALLOCA]])
// CHECK:         call void @llvm.stackrestore(ptr [[STACK_BEFORE_FIRST_ALLOCA]])
// 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 : $()
}