@@ -68,19 +68,17 @@ struct AliasAnalysis {
68
68
let inst = bridgedInst. instruction
69
69
let val = bridgedVal. value
70
70
let path = AliasAnalysis . getPtrOrAddressPath ( for: val)
71
- if let apply = inst as? ApplySite {
72
- let effect = getMemoryEffect ( of: apply, for: val, path: path, context)
73
- switch ( effect. read, effect. write) {
74
- case ( false , false ) : return . None
75
- case ( true , false ) : return . MayRead
76
- case ( false , true ) : return . MayWrite
77
- case ( true , true ) : return . MayReadWrite
71
+ switch inst {
72
+ case let apply as ApplySite :
73
+ return getMemoryEffect ( ofApply: apply, for: val, path: path, context) . bridged
74
+ case let builtin as BuiltinInst :
75
+ return getMemoryEffect ( ofBuiltin: builtin, for: val, path: path, context) . bridged
76
+ default :
77
+ if val. at ( path) . isEscaping ( using: EscapesToInstructionVisitor ( target: inst, isAddress: true ) , context) {
78
+ return . MayReadWrite
78
79
}
80
+ return . None
79
81
}
80
- if val. at ( path) . isEscaping ( using: EscapesToInstructionVisitor ( target: inst, isAddress: true ) , context) {
81
- return . MayReadWrite
82
- }
83
- return . None
84
82
} ,
85
83
86
84
// isObjReleasedFn
@@ -121,7 +119,7 @@ struct AliasAnalysis {
121
119
}
122
120
}
123
121
124
- private func getMemoryEffect( of apply: ApplySite , for address: Value , path: SmallProjectionPath , _ context: FunctionPassContext ) -> SideEffects . Memory {
122
+ private func getMemoryEffect( ofApply apply: ApplySite , for address: Value , path: SmallProjectionPath , _ context: FunctionPassContext ) -> SideEffects . Memory {
125
123
let calleeAnalysis = context. calleeAnalysis
126
124
let visitor = SideEffectsVisitor ( apply: apply, calleeAnalysis: calleeAnalysis, isAddress: true )
127
125
let memoryEffects : SideEffects . Memory
@@ -132,7 +130,7 @@ private func getMemoryEffect(of apply: ApplySite, for address: Value, path: Smal
132
130
memoryEffects = result. memory
133
131
} else {
134
132
// `address` has unknown escapes. So we have to take the global effects of the called function(s).
135
- memoryEffects = calleeAnalysis. getSideEffects ( of : apply) . memory
133
+ memoryEffects = calleeAnalysis. getSideEffects ( ofApply : apply) . memory
136
134
}
137
135
// Do some magic for `let` variables. Function calls cannot modify let variables.
138
136
// The only exception is that the let variable is directly passed to an indirect out of the
@@ -144,14 +142,28 @@ private func getMemoryEffect(of apply: ApplySite, for address: Value, path: Smal
144
142
return memoryEffects
145
143
}
146
144
145
+ private func getMemoryEffect( ofBuiltin builtin: BuiltinInst , for address: Value , path: SmallProjectionPath , _ context: FunctionPassContext ) -> SideEffects . Memory {
146
+
147
+ switch builtin. id {
148
+ case . Once, . OnceWithContext:
149
+ if !address. at ( path) . isEscaping ( using: AddressVisibleByBuiltinOnceVisitor ( ) , context) {
150
+ return SideEffects . Memory ( )
151
+ }
152
+ let callee = builtin. operands [ 1 ] . value
153
+ return context. calleeAnalysis. getSideEffects ( ofCallee: callee) . memory
154
+ default :
155
+ return builtin. memoryEffects
156
+ }
157
+ }
158
+
147
159
private func getOwnershipEffect( of apply: ApplySite , for value: Value , path: SmallProjectionPath , _ context: FunctionPassContext ) -> SideEffects . Ownership {
148
160
let visitor = SideEffectsVisitor ( apply: apply, calleeAnalysis: context. calleeAnalysis, isAddress: false )
149
161
if let result = value. at ( path) . visit ( using: visitor, context) {
150
162
// The resulting effects are the argument effects to which `value` escapes to.
151
163
return result. ownership
152
164
} else {
153
165
// `value` has unknown escapes. So we have to take the global effects of the called function(s).
154
- return visitor. calleeAnalysis. getSideEffects ( of : apply) . ownership
166
+ return visitor. calleeAnalysis. getSideEffects ( ofApply : apply) . ownership
155
167
}
156
168
}
157
169
@@ -180,6 +192,11 @@ private struct SideEffectsVisitor : EscapeVisitorWithResult {
180
192
var followLoads : Bool { !isAddress }
181
193
}
182
194
195
+ private struct AddressVisibleByBuiltinOnceVisitor : EscapeVisitor {
196
+ var followTrivialTypes : Bool { true }
197
+ var followLoads : Bool { false }
198
+ }
199
+
183
200
/// Lets `ProjectedValue.isEscaping` return true if the value is "escaping" to the `target` instruction.
184
201
private struct EscapesToInstructionVisitor : EscapeVisitor {
185
202
let target : Instruction
@@ -229,3 +246,13 @@ private struct IsIndirectResultWalker: AddressDefUseWalker {
229
246
}
230
247
}
231
248
249
+ private extension SideEffects . Memory {
250
+ var bridged : swift . MemoryBehavior {
251
+ switch ( read, write) {
252
+ case ( false , false ) : return . None
253
+ case ( true , false ) : return . MayRead
254
+ case ( false , true ) : return . MayWrite
255
+ case ( true , true ) : return . MayReadWrite
256
+ }
257
+ }
258
+ }
0 commit comments