File: globalopt_global_propagation.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 (254 lines) | stat: -rw-r--r-- 7,784 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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// RUN: %target-swift-frontend -parse-as-library -O -emit-sil %s | %FileCheck %s

// REQUIRES: swift_in_compiler

// Check that values of internal and private global variables, which are provably assigned only 
// once, are propagated into their uses and enable further optimizations like constant
// propagation, simplifications, etc.

// Define some global variables.

public var VD = 3.1415
public var VI = 100

private var PVD = 3.1415
private var PVI = 100
private var PVIAssignTwice = 1
private var PVITakenAddress = 1


internal var IVD = 3.1415
internal var IVI = 100
internal var IVIAssignTwice = 1
internal var IVITakenAddress = 1

// Taking the address of a global should prevent from performing the propagation of its value.
@inline(never)
@_optimize(none)
public func takeInout<T>(_ x: inout T) {
}

// Compiler should detect that we assign a global here as well and prevent a global optimization.
public func assignSecondTime() {
  PVIAssignTwice = 2
  IVIAssignTwice = 2
}

// Having multiple assignments to a global should prevent from performing the propagation of its value.

// Loads from private global variables can be removed, 
// because they cannot be changed outside of this source file.
// CHECK-LABEL: sil [noinline] @$s28globalopt_global_propagation013test_private_B11_var_doubleSdyF
// CHECK: bb0:
// CHECK-NOT: global_addr
// CHECK: float_literal
// CHECK: struct
// CHECK: return
@inline(never)
public func test_private_global_var_double() -> Double {
  return PVD + 1.0 
}

// Loads from private global variables can be removed, 
// because they cannot be changed outside of this source file.
// CHECK-LABEL: sil [noinline] @$s28globalopt_global_propagation013test_private_B8_var_intSiyF
// CHECK: bb0:
// CHECK-NOT: global_addr
// CHECK: integer_literal
// CHECK: struct
// CHECK: return
@inline(never)
public func test_private_global_var_int() -> Int {
  return PVI + 1
}

// Loads from internal global variables can be removed if this is a WMO compilation, because
// they cannot be changed outside of this module.
// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation014test_internal_B11_var_doubleSdyF
// CHECK-WMO: bb0:
// CHECK-WMO-NOT: global_addr
// CHECK-WMO: float_literal
// CHECK-WMO: struct
// CHECK-WMO: return
@inline(never)
public func test_internal_global_var_double() -> Double {
  return IVD + 1.0 
}

// Loads from internal global variables can be removed if this is a WMO compilation, because
// they cannot be changed outside of this module.
// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation014test_internal_B8_var_intSiyF
// CHECK_WMO: bb0:
// CHECK-WMO-NOT: global_addr
// CHECK-WMO: integer_literal
// CHECK-WMO: struct
// CHECK_WMO: return
@inline(never)
public func test_internal_global_var_int() -> Int {
  return IVI + 1
}

// Loads from public global variables cannot be removed, because their values could be changed elsewhere.
// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation012test_public_B11_var_doubleSdyF
// CHECK-WMO: bb0:
// CHECK-WMO-NEXT: global_addr
// CHECK-WMO-NEXT: begin_access [read] [dynamic]
// CHECK-WMO-NEXT: struct_element_addr
// CHECK-WMO-NEXT: load
@inline(never)
public func test_public_global_var_double() -> Double {
  return VD + 1.0 
}


// Loads from public global variables cannot be removed, because their values could be changed elsewhere.
// CHECK-LABEL: sil [noinline] @$s28globalopt_global_propagation012test_public_B8_var_intSiyF
// CHECK: bb0: 
// CHECK-NEXT: global_addr
// CHECK-NEXT: begin_access [read] [dynamic]
// CHECK-NEXT: struct_element_addr
// CHECK-NEXT: load
@inline(never)
public func test_public_global_var_int() -> Int {
  return VI + 1
}

// Values of globals cannot be propagated as there are multiple assignments to it.
// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation026test_internal_and_private_B25_var_with_two_assignmentsSiyF
// CHECK-WMO: bb0: 
// CHECK-WMO-DAG: global_addr
// CHECK-WMO-DAG: struct_element_addr
// CHECK-WMO-DAG: load
// CHECK-WMO-DAG: global_addr
// CHECK-WMO-DAG: struct_element_addr
// CHECK-WMO-DAG: load
// CHECK-WMO: return
@inline(never)
public func test_internal_and_private_global_var_with_two_assignments() -> Int {
  return IVIAssignTwice + PVIAssignTwice
}

// Values of globals cannot be propagated as their address was taken and
// therefore their value could have been changed elsewhere.
// CHECK-WMO-LABEL: sil @$s28globalopt_global_propagation05test_B13_take_addressSiyF
// CHECK-WMO: bb0:
// CHECK-WMO: global_addr
// CHECK-WMO: global_addr
// CHECK-WMO: struct_element_addr
// CHECK-WMO: load
// CHECK-WMO: struct_element_addr
// CHECK-WMO: load
// CHECK-WMO: return
public func test_global_take_address() -> Int {
  takeInout(&PVITakenAddress)
  takeInout(&IVITakenAddress)
  return IVITakenAddress + PVITakenAddress
}

struct IntWrapper1 {
  let val: Int
}

struct IntWrapper2 {
  let val: IntWrapper1
}

struct IntWrapper3 {
  let val: IntWrapper2
}

struct IntWrapper4 {
  let val:  IntWrapper2
  let val2: IntWrapper1
}

let IW3 = IntWrapper3(val: IntWrapper2(val: IntWrapper1(val: 10)))


let IW4 = IntWrapper4(val: IntWrapper2(val: IntWrapper1(val: 10)), val2: IntWrapper1(val: 100))

// Test accessing single Int wrapped into multiple structs, where each struct has only one field.
// CHECK-LABEL: sil [noinline] @$s28globalopt_global_propagation34test_let_struct_wrapped_single_intSiyF
// CHECK: bb0:
// CHECK-NOT: global_addr
// CHECK: integer_literal
// CHECK: struct
// CHECK: return

// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation34test_let_struct_wrapped_single_intSiyF
// CHECK-WMO: bb0:
// CHECK-WMO-NOT: global_addr
// CHECK-WMO: integer_literal
// CHECK-WMO: struct
// CHECK-WMO: return
@inline(never)
public func test_let_struct_wrapped_single_int() -> Int {
  return IW3.val.val.val + 1
}

// Test accessing multiple Int fields wrapped into multiple structs, where each struct may have
// multiple fields.
// CHECK-LABEL: sil [noinline] @$s28globalopt_global_propagation37test_let_struct_wrapped_multiple_intsSiyF
// CHECK: bb0:
// CHECK-NOT: global_addr
// CHECK: integer_literal
// CHECK: struct
// CHECK: return

// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation37test_let_struct_wrapped_multiple_intsSiyF
// CHECK-WMO: bb0:
// CHECK-WMO-NOT: global_addr
// CHECK-WMO: integer_literal
// CHECK-WMO: struct
// CHECK-WMO: return
@inline(never)
public func test_let_struct_wrapped_multiple_ints() -> Int {
  return IW4.val.val.val + IW4.val2.val + 1
}


let IT1 = ((10, 20), 30, 40)

let IT2 = (100, 200, 300)

// Test accessing multiple Int fields wrapped into multiple tuples, where each tuple may have
// multiple fields.
// CHECK-LABEL: sil [noinline] @$s28globalopt_global_propagation27test_let_tuple_wrapped_intsSiyF
// CHECK: bb0:
// CHECK-NOT: global_addr
// CHECK: integer_literal
// CHECK: struct
// CHECK: return

// CHECK-WMO-LABEL: sil [noinline] @$s28globalopt_global_propagation27test_let_tuple_wrapped_intsSiyF
// CHECK-WMO: bb0:
// CHECK-WMO-NOT: global_addr
// CHECK-WMO: integer_literal
// CHECK-WMO: struct
// CHECK-WMO: return
@inline(never)
public func test_let_tuple_wrapped_ints() -> Int {
  return IT1.0.0 + IT2.1
}

class Foo {
  fileprivate static var x: Int = 0
}

// CHECK-LABEL: sil @$s28globalopt_global_propagation25test_optimize_init_staticSiyF
// CHECK: bb0:
// CHECK-NOT: global_addr
// CHECK-NEXT: integer_literal
// CHECK-NEXT: struct
// CHECK-NEXT: return

// CHECK-WMO-LABEL: sil @$s28globalopt_global_propagation25test_optimize_init_staticSiyF
// CHECK-WMO: bb0:
// CHECK-WMO-NOT: global_addr
// CHECK-WMO-NEXT: integer_literal
// CHECK-WMO-NEXT: struct
// CHECK-WMO-NEXT: return
public func test_optimize_init_static() -> Int {
  return Foo.x
}