Skip to content

Commit d177df9

Browse files
Merge pull request swiftlang#76440 from nate-chandler/rdar134198292
[Outliner] Handle multiple consumes of a value.
2 parents d4c865c + e7365aa commit d177df9

File tree

2 files changed

+185
-1
lines changed

2 files changed

+185
-1
lines changed

lib/SILOptimizer/Transforms/Outliner.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1196,6 +1196,11 @@ bool ObjCMethodCall::matchInstSequence(SILBasicBlock::iterator I) {
11961196
unsigned Idx = 0;
11971197
IsBridgedArgument.resize(BridgedCall->getNumArguments(), false);
11981198
IsGuaranteedArgument.resize(BridgedCall->getNumArguments(), false);
1199+
// Map from owned values whose bridged versions we've seen in the apply to
1200+
// the index in the apply at which they appear or UINT_MAX if we've seen them
1201+
// more than once (which means we've already nulled out all the
1202+
// BridgedArguments' ReleaseAfterBridge).
1203+
llvm::DenseMap<SILValue, unsigned> seenOwnedBridgedValues;
11991204
for (auto &Param : BridgedCall->getArgumentOperands()) {
12001205
unsigned CurIdx = Idx++;
12011206

@@ -1216,8 +1221,31 @@ bool ObjCMethodCall::matchInstSequence(SILBasicBlock::iterator I) {
12161221

12171222
BridgedArguments.push_back(BridgedArg);
12181223
IsBridgedArgument.set(CurIdx);
1219-
if (BridgedArg.isGuaranteed())
1224+
if (BridgedArg.isGuaranteed()) {
12201225
IsGuaranteedArgument.set(CurIdx);
1226+
continue;
1227+
}
1228+
// Record that this owned value was used at CurIdx.
1229+
auto pair =
1230+
seenOwnedBridgedValues.insert({BridgedArg.BridgedValue, CurIdx});
1231+
auto firstSighting = pair.second;
1232+
if (firstSighting) {
1233+
continue;
1234+
}
1235+
// This owned value was already seen. Convert the current argument to
1236+
// guaranteed and the previous argument as well if necessary.
1237+
auto iterator = pair.first;
1238+
if (iterator->second != UINT_MAX) {
1239+
// This is the _second_ time the value has been seen. Clear the previous
1240+
// occurrence's ReleaseAfterBridge and sink the destroy after the apply.
1241+
BridgedArguments[iterator->second].ReleaseAfterBridge->moveAfter(
1242+
BridgedCall);
1243+
BridgedArguments[iterator->second].ReleaseAfterBridge = nullptr;
1244+
IsGuaranteedArgument.set(iterator->second);
1245+
iterator->second = UINT_MAX;
1246+
}
1247+
BridgedArguments[CurIdx].ReleaseAfterBridge = nullptr;
1248+
IsGuaranteedArgument.set(CurIdx);
12211249
}
12221250

12231251
// Try to match a bridged return value.

test/SILOptimizer/outliner.sil

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,159 @@ bb7(%64 : $Optional<Data>):
105105
%102 = tuple ()
106106
return %102 : $()
107107
}
108+
109+
sil @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
110+
sil @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String
111+
sil @get : $@convention(thin) () -> @owned String
112+
113+
@objc class Ty {
114+
@objc static func take2(_: String?, _: String?)
115+
@objc static func take3(_: String?, _: String?, _: String?)
116+
}
117+
118+
// CHECK-LABEL: sil [Osize] [ossa] @reuse_owned_2 : {{.*}} {
119+
// CHECK: [[NATIVE:%[^,]+]] = apply {{%[^,]+}}()
120+
// CHECK: [[TY:%[^,]+]] = metatype
121+
// CHECK: [[OUTLINED:%[^,]+]] = function_ref @$s4main2TyC5take2yySSSg_AEtFZToTembgbgnn_
122+
// CHECK: apply [[OUTLINED]]([[NATIVE]], [[NATIVE]], [[TY]])
123+
// CHECK: destroy_value [[NATIVE]] : $String
124+
// CHECK-LABEL: } // end sil function 'reuse_owned_2'
125+
sil [ossa] [Osize] @reuse_owned_2 : $@convention(thin) () -> () {
126+
bb0:
127+
%get = function_ref @get : $@convention(thin) () -> @owned String
128+
%native = apply %get() : $@convention(thin) () -> @owned String
129+
%ty = metatype $@objc_metatype Ty.Type
130+
%bridge = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
131+
%bridged1 = apply %bridge(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
132+
%optbridged1 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged1 : $NSString
133+
%bridge2 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
134+
%bridged2 = apply %bridge2(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
135+
%optbridged2 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged2 : $NSString
136+
destroy_value %native : $String
137+
%take2 = objc_method %ty : $@objc_metatype Ty.Type, #Ty.take2!foreign : (Ty.Type) -> (String?, String?) -> (), $@convention(objc_method) (Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
138+
%27 = apply %take2(%optbridged1, %optbridged2, %ty) : $@convention(objc_method) (Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
139+
destroy_value %optbridged2 : $Optional<NSString>
140+
destroy_value %optbridged1 : $Optional<NSString>
141+
%31 = tuple ()
142+
return %31 : $()
143+
}
144+
145+
// CHECK-LABEL: sil [Osize] [ossa] @reuse_owned_3 : {{.*}} {
146+
// CHECK: [[NATIVE:%[^,]+]] = apply {{%[^,]+}}()
147+
// CHECK: [[TY:%[^,]+]] = metatype
148+
// CHECK: [[OUTLINED:%[^,]+]] = function_ref @$s4main2TyC5take3yySSSg_A2EtFZToTembgbgbgnn_
149+
// CHECK: apply [[OUTLINED]]([[NATIVE]], [[NATIVE]], [[NATIVE]], [[TY]])
150+
// CHECK: destroy_value [[NATIVE]] : $String
151+
// CHECK-LABEL: } // end sil function 'reuse_owned_3'
152+
sil [ossa] [Osize] @reuse_owned_3 : $@convention(thin) () -> () {
153+
bb0:
154+
%get = function_ref @get : $@convention(thin) () -> @owned String
155+
%native = apply %get() : $@convention(thin) () -> @owned String
156+
%ty = metatype $@objc_metatype Ty.Type
157+
%bridge = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
158+
%bridged1 = apply %bridge(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
159+
%optbridged1 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged1 : $NSString
160+
%bridge2 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
161+
%bridged2 = apply %bridge2(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
162+
%optbridged2 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged2 : $NSString
163+
%bridge3 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
164+
%bridged3 = apply %bridge3(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
165+
%optbridged3 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged3 : $NSString
166+
destroy_value %native : $String
167+
%take2 = objc_method %ty : $@objc_metatype Ty.Type, #Ty.take3!foreign : (Ty.Type) -> (String?, String?, String?) -> (), $@convention(objc_method) (Optional<NSString>, Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
168+
%27 = apply %take2(%optbridged1, %optbridged2, %optbridged3, %ty) : $@convention(objc_method) (Optional<NSString>, Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
169+
destroy_value %optbridged3 : $Optional<NSString>
170+
destroy_value %optbridged2 : $Optional<NSString>
171+
destroy_value %optbridged1 : $Optional<NSString>
172+
%31 = tuple ()
173+
return %31 : $()
174+
}
175+
176+
// CHECK-LABEL: sil [Osize] [ossa] @reuse_guaranteed_2 : {{.*}} {
177+
// CHECK: bb0([[NATIVE:%[^,]+]] :
178+
// CHECK: [[TY:%[^,]+]] = metatype
179+
// CHECK: [[OUTLINED:%[^,]+]] = function_ref @$s4main2TyC5take2yySSSg_AEtFZToTembgbgnn_
180+
// CHECK: apply [[OUTLINED]]([[NATIVE]], [[NATIVE]], [[TY]])
181+
// CHECK-LABEL: } // end sil function 'reuse_guaranteed_2'
182+
sil [ossa] [Osize] @reuse_guaranteed_2 : $@convention(thin) (@guaranteed String) -> () {
183+
bb0(%native : @guaranteed $String):
184+
%ty = metatype $@objc_metatype Ty.Type
185+
%bridge = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
186+
%bridged1 = apply %bridge(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
187+
%optbridged1 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged1 : $NSString
188+
%bridge2 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
189+
%bridged2 = apply %bridge2(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
190+
%optbridged2 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged2 : $NSString
191+
%take2 = objc_method %ty : $@objc_metatype Ty.Type, #Ty.take2!foreign : (Ty.Type) -> (String?, String?) -> (), $@convention(objc_method) (Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
192+
%27 = apply %take2(%optbridged1, %optbridged2, %ty) : $@convention(objc_method) (Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
193+
destroy_value %optbridged2 : $Optional<NSString>
194+
destroy_value %optbridged1 : $Optional<NSString>
195+
%31 = tuple ()
196+
return %31 : $()
197+
}
198+
199+
// CHECK-LABEL: sil [Osize] [ossa] @reuse_guaranteed_3 : {{.*}} {
200+
// CHECK: bb0([[NATIVE:%[^,]+]] :
201+
// CHECK: [[TY:%[^,]+]] = metatype
202+
// CHECK: [[OUTLINED:%[^,]+]] = function_ref @$s4main2TyC5take3yySSSg_A2EtFZToTembgbgbgnn_
203+
// CHECK: apply [[OUTLINED]]([[NATIVE]], [[NATIVE]], [[NATIVE]], [[TY]])
204+
// CHECK-LABEL: } // end sil function 'reuse_guaranteed_3'
205+
sil [ossa] [Osize] @reuse_guaranteed_3 : $@convention(thin) (@guaranteed String) -> () {
206+
bb0(%native : @guaranteed $String):
207+
%ty = metatype $@objc_metatype Ty.Type
208+
%bridge = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
209+
%bridged1 = apply %bridge(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
210+
%optbridged1 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged1 : $NSString
211+
%bridge2 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
212+
%bridged2 = apply %bridge2(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
213+
%optbridged2 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged2 : $NSString
214+
%bridge3 = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF : $@convention(method) (@guaranteed String) -> @owned NSString
215+
%bridged3 = apply %bridge3(%native) : $@convention(method) (@guaranteed String) -> @owned NSString
216+
%optbridged3 = enum $Optional<NSString>, #Optional.some!enumelt, %bridged3 : $NSString
217+
%take2 = objc_method %ty : $@objc_metatype Ty.Type, #Ty.take3!foreign : (Ty.Type) -> (String?, String?, String?) -> (), $@convention(objc_method) (Optional<NSString>, Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
218+
%27 = apply %take2(%optbridged1, %optbridged2, %optbridged3, %ty) : $@convention(objc_method) (Optional<NSString>, Optional<NSString>, Optional<NSString>, @objc_metatype Ty.Type) -> ()
219+
destroy_value %optbridged3 : $Optional<NSString>
220+
destroy_value %optbridged2 : $Optional<NSString>
221+
destroy_value %optbridged1 : $Optional<NSString>
222+
%31 = tuple ()
223+
return %31 : $()
224+
}
225+
226+
// CHECK-LABEL: sil shared [serialized] [noinline] [ossa] @$s4main2TyC5take2yySSSg_AEtFZToTembgbgnn_ : {{.*}} {
227+
// CHECK: bb0([[FIRST:%[^,]+]] : @guaranteed
228+
// CHECK-SAME: , [[SECOND:%[^,]+]] : @guaranteed
229+
// CHECK-SAME: , [[TY:%[^,]+]] : $@objc_metatype
230+
// CHECK-SAME: ):
231+
// CHECK: [[CALLEE:%[^,]+]] = objc_method [[TY]]
232+
// CHECK: [[BRIDGE_1:%[^,]+]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
233+
// CHECK: [[BRIDGED_1:%[^,]+]] = apply [[BRIDGE_1]]([[FIRST]])
234+
// CHECK: [[OPT_BRIDGED_1:%[^,]+]] = enum $Optional<NSString>, #Optional.some!enumelt, [[BRIDGED_1]]
235+
// CHECK: [[BRIDGE_2:%[^,]+]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
236+
// CHECK: [[BRIDGED_2:%[^,]+]] = apply [[BRIDGE_2]]([[SECOND]])
237+
// CHECK: [[OPT_BRIDGED_2:%[^,]+]] = enum $Optional<NSString>, #Optional.some!enumelt, [[BRIDGED_2]]
238+
// CHECK: apply [[CALLEE]]([[OPT_BRIDGED_1]], [[OPT_BRIDGED_2]], [[TY]])
239+
// CHECK: destroy_value [[OPT_BRIDGED_2]]
240+
// CHECK: destroy_value [[OPT_BRIDGED_1]]
241+
// CHECK-LABEL: } // end sil function '$s4main2TyC5take2yySSSg_AEtFZToTembgbgnn_'
242+
243+
// CHECK-LABEL: sil shared [serialized] [noinline] [ossa] @$s4main2TyC5take3yySSSg_A2EtFZToTembgbgbgnn_ : {{.*}} {
244+
// CHECK: bb0([[FIRST:%[^,]+]] : @guaranteed
245+
// CHECK-SAME: , [[SECOND:%[^,]+]] : @guaranteed
246+
// CHECK-SAME: , [[THIRD:%[^,]+]] : @guaranteed
247+
// CHECK-SAME: , [[TY:%[^,]+]] : $@objc_metatype
248+
// CHECK-SAME: ):
249+
// CHECK: [[CALLEE:%[^,]+]] = objc_method [[TY]]
250+
// CHECK: [[BRIDGE_1:%[^,]+]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
251+
// CHECK: [[BRIDGED_1:%[^,]+]] = apply [[BRIDGE_1]]([[FIRST]])
252+
// CHECK: [[OPT_BRIDGED_1:%[^,]+]] = enum $Optional<NSString>, #Optional.some!enumelt, [[BRIDGED_1]]
253+
// CHECK: [[BRIDGE_2:%[^,]+]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
254+
// CHECK: [[BRIDGED_2:%[^,]+]] = apply [[BRIDGE_2]]([[SECOND]])
255+
// CHECK: [[OPT_BRIDGED_2:%[^,]+]] = enum $Optional<NSString>, #Optional.some!enumelt, [[BRIDGED_2]]
256+
// CHECK: [[BRIDGE_3:%[^,]+]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
257+
// CHECK: [[BRIDGED_3:%[^,]+]] = apply [[BRIDGE_3]]([[THIRD]])
258+
// CHECK: [[OPT_BRIDGED_3:%[^,]+]] = enum $Optional<NSString>, #Optional.some!enumelt, [[BRIDGED_3]]
259+
// CHECK: apply [[CALLEE]]([[OPT_BRIDGED_1]], [[OPT_BRIDGED_2]], [[OPT_BRIDGED_3]], [[TY]])
260+
// CHECK: destroy_value [[OPT_BRIDGED_3]]
261+
// CHECK: destroy_value [[OPT_BRIDGED_2]]
262+
// CHECK: destroy_value [[OPT_BRIDGED_1]]
263+
// CHECK-LABEL: } // end sil function '$s4main2TyC5take3yySSSg_A2EtFZToTembgbgbgnn_'

0 commit comments

Comments
 (0)