File: mandatory_inlining.swift

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 (216 lines) | stat: -rw-r--r-- 5,798 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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// RUN: %target-swift-frontend -sil-verify-all -primary-file %s -emit-sil -o - -verify | %FileCheck %s
// RUN: %target-swift-frontend -sil-verify-all -primary-file %s -emit-sil -o - -verify

// These tests are deliberately shallow, because I do not want to depend on the
// specifics of SIL generation, which might change for reasons unrelated to this
// pass

func foo(_ x: Float) -> Float {
  return bar(x);
}

// CHECK-LABEL: sil hidden @$s18mandatory_inlining3foo{{[_0-9a-zA-Z]*}}F
// CHECK: bb0(%0 : $Float):
// CHECK-NEXT: debug_value %0 : $Float, let, name "x"
// CHECK-NEXT: return %0

@_transparent func bar(_ x: Float) -> Float {
  return baz(x)
}

// CHECK-LABEL: sil hidden [transparent] @$s18mandatory_inlining3bar{{[_0-9a-zA-Z]*}}F
  // CHECK-NOT: function_ref
  // CHECK-NOT: apply
  // CHECK: return

@_transparent func baz(_ x: Float) -> Float {
  return x
}

// CHECK-LABEL: sil hidden [transparent] @$s18mandatory_inlining3baz{{[_0-9a-zA-Z]*}}F
// CHECK: return

func spam(_ x: Int) -> Int {
  return x
}

// CHECK-LABEL: sil hidden @$s18mandatory_inlining4spam{{[_0-9a-zA-Z]*}}F

@_transparent func ham(_ x: Int) -> Int {
  return spam(x)
}

// CHECK-LABEL: sil hidden [transparent] @$s18mandatory_inlining3ham{{[_0-9a-zA-Z]*}}F
  // CHECK: function_ref @$s18mandatory_inlining4spam{{[_0-9a-zA-Z]*}}F
  // CHECK: apply
  // CHECK: return

func eggs(_ x: Int) -> Int {
  return ham(x)
}

// CHECK-LABEL: sil hidden @$s18mandatory_inlining4eggs{{[_0-9a-zA-Z]*}}F
  // CHECK: function_ref @$s18mandatory_inlining4spam{{[_0-9a-zA-Z]*}}F
  // CHECK: apply
  // CHECK: return

@_transparent func call_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
  return x()
}

func test_auto_closure_with_capture(_ x: Bool) -> Bool {
  return call_auto_closure(x)
}

// This should be fully inlined and simply return x; however, there's a lot of
// non-SSA cruft that I don't want this test to depend on, so I'm just going
// to verify that it doesn't have any function applications left

// CHECK-LABEL: sil hidden @{{.*}}test_auto_closure_with_capture
  // CHECK-NOT: = apply
  // CHECK: return

func test_auto_closure_without_capture() -> Bool {
  return call_auto_closure(false)
}

// This should be fully inlined and simply return false, which is easier to check for

// CHECK-LABEL: sil hidden @$s18mandatory_inlining33test_auto_closure_without_captureSbyF
  // CHECK: [[FV:%.*]] = integer_literal $Builtin.Int1, 0
  // CHECK: [[FALSE:%.*]] = struct $Bool ([[FV:%.*]] : $Builtin.Int1)
  // CHECK: return [[FALSE]]

infix operator &&& : LogicalConjunctionPrecedence
infix operator ||| : LogicalDisjunctionPrecedence

@_transparent func &&& (lhs: Bool, rhs: @autoclosure () -> Bool) -> Bool {
  if lhs {
    return rhs()
  }

  return false
}

@_transparent func ||| (lhs: Bool, rhs: @autoclosure () -> Bool) -> Bool {
  if lhs {
    return true
  }

  return rhs()
}

func test_chained_short_circuit(_ x: Bool, y: Bool, z: Bool) -> Bool {
  return x &&& (y ||| z)
}

// The test below just makes sure there are no uninlined [transparent] calls
// left (i.e. the autoclosure and the short-circuiting boolean operators are
// recursively inlined properly)

// CHECK-LABEL: sil hidden @$s18mandatory_inlining26test_chained_short_circuit{{[_0-9a-zA-Z]*}}F
  // CHECK-NOT: = apply [transparent]
  // CHECK: return


// Union element constructors should be inlined automatically.
enum X {
  case onetransp
  case twotransp
}

func testInlineUnionElement() -> X {
  return X.onetransp
  // CHECK-LABEL: sil hidden @$s18mandatory_inlining22testInlineUnionElementAA1XOyF
  // CHECK: enum $X, #X.onetransp!enumelt
  // CHECK-NOT: = apply
  // CHECK: return
}



@_transparent
func call_let_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
  return x()
}

// CHECK-LABEL: sil hidden @{{.*}}test_let_auto_closure_with_value_capture
// CHECK: bb0(%0 : $Bool):
// CHECK-NEXT: debug_value %0 : $Bool
// CHECK-NEXT: return %0 : $Bool
// CHECK-LABEL: // end sil function '{{.*}}test_let_auto_closure_with_value_capture
func test_let_auto_closure_with_value_capture(_ x: Bool) -> Bool {
  return call_let_auto_closure(x)
}


class C {}

// CHECK-LABEL: sil hidden [transparent] @$s18mandatory_inlining25class_constrained_generic{{[_0-9a-zA-Z]*}}F
@_transparent
func class_constrained_generic<T : C>(_ o: T) -> AnyClass? {
  // CHECK: return
  return T.self
}

// CHECK-LABEL: sil hidden @$s18mandatory_inlining6invokeyyAA1CCF : $@convention(thin) (@guaranteed C) -> () {
func invoke(_ c: C) {
  // CHECK-NOT: function_ref @$s18mandatory_inlining25class_constrained_generic{{[_0-9a-zA-Z]*}}F
  // CHECK-NOT: apply
  _ = class_constrained_generic(c)
  // CHECK: return
}

// Make sure we don't crash.
@_transparent
public func mydo(_ what: @autoclosure () -> ()) {
  what()
}
public class A {
  public func bar() {}
  public func foo(_ act: (@escaping () ->()) -> ()) {
    act { [unowned self] in
      mydo( self.bar() )
    }
  }
}

// This used to crash during mandatory inlining because noreturn folding would
// create sil instructions with undef in unreachable code.
func dontCrash() {
  fatalError() // expected-note {{a call to a never-returning function}}
  let k = "foo" // expected-warning {{will never be executed}}
  switch k {
  case "bar":
    return
  default:
    fatalError("baz \(k)")
  }
}

func switchLoopWithPartialApplyCallee(reportError: ((String) -> (Void))?) {
  let reportError = reportError ?? { error in
    print(error)
  }

  for _ in 0..<1 {
    reportError("foo bar baz")
  }
}

func switchLoopWithPartialApplyCaller() {
  switchLoopWithPartialApplyCallee { error in
      print(error)
  }
}

private class Cl {
  func foo<E: Error>(_ e: E.Type) throws(E) {
  }
}


private func devirtualizeClassMethodWithTypedThrow<E: Error>(_ x: Cl, e: E.Type) {
  try! x.foo(e)
}