Skip to content

Commit a903805

Browse files
committed
[Outliner] Add consuming bridged property pattern.
Previously, for the BridgedProperty pattern, there were two flavors of outlined function that would be formed, varying on the ownership of the instance whose field is being access: (1) guaranteed_in -- for use by addresses (2) unowned -- for use by values which were not destroyed until some time after the pattern of interest is matched Now that the lifetime of the instance may be shortened to just after the call to the objc method, the latter of these is not appropriate for values. We would have to re-extend the lifetime until after the method returns. Instead, here, we add a new variant (3) owned -- for use by values which were destroyed just after the objc method call Doing so requires new mangling.
1 parent 9b290cd commit a903805

File tree

3 files changed

+61
-31
lines changed

3 files changed

+61
-31
lines changed

lib/Demangling/Demangler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2800,7 +2800,7 @@ std::string Demangler::demangleBridgedMethodParams() {
28002800
switch (kind) {
28012801
default:
28022802
return std::string();
2803-
case 'p': case 'a': case 'm':
2803+
case 'o': case 'p': case 'a': case 'm':
28042804
Str.push_back(kind);
28052805
}
28062806

lib/SILOptimizer/Transforms/Outliner.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class OutlinerMangler : public Mangle::ASTMangler {
5050
/// The kind of method bridged.
5151
enum MethodKind : unsigned {
5252
BridgedProperty,
53+
BridgedProperty_Consuming,
5354
BridgedPropertyAddress,
5455
BridgedMethod,
5556
};
@@ -69,10 +70,12 @@ class OutlinerMangler : public Mangle::ASTMangler {
6970
Kind(BridgedMethod), IsReturnBridged(ReturnBridged) {}
7071

7172
/// Create an mangler for an outlined bridged property.
72-
OutlinerMangler(SILDeclRef Method, bool IsAddress)
73+
OutlinerMangler(SILDeclRef Method, bool IsAddress, bool ConsumesValue)
7374
: IsParameterBridged(nullptr), IsParameterGuaranteed(nullptr),
7475
MethodDecl(Method),
75-
Kind(IsAddress ? BridgedPropertyAddress : BridgedProperty),
76+
Kind(IsAddress ? BridgedPropertyAddress
77+
: (ConsumesValue ? BridgedProperty_Consuming
78+
: BridgedProperty)),
7679
IsReturnBridged(true) {}
7780

7881
std::string mangle();
@@ -82,6 +85,8 @@ class OutlinerMangler : public Mangle::ASTMangler {
8285
switch (Kind) {
8386
case BridgedProperty:
8487
return 'p';
88+
case BridgedProperty_Consuming:
89+
return 'o';
8590
case BridgedPropertyAddress:
8691
return 'a';
8792
case BridgedMethod:
@@ -234,6 +239,9 @@ class BridgedProperty : public OutlinePattern {
234239
ObjCMethodInst *ObjCMethod;
235240
SILInstruction *Release;
236241
ApplyInst *PropApply;
242+
SILInstruction *UnpairedRelease; // A release_value | destroy_value following
243+
// the apply which isn't paired to
244+
// load [copy] | strong_retain first value.
237245

238246
public:
239247
bool matchInstSequence(SILBasicBlock::iterator I) override;
@@ -269,12 +277,14 @@ void BridgedProperty::clearState() {
269277
ObjCMethod = nullptr;
270278
Release = nullptr;
271279
PropApply = nullptr;
280+
UnpairedRelease = nullptr;
272281
OutlinedName.clear();
273282
}
274283

275284
std::string BridgedProperty::getOutlinedFunctionName() {
276285
if (OutlinedName.empty()) {
277-
OutlinerMangler Mangler(ObjCMethod->getMember(), isa<LoadInst>(FirstInst));
286+
OutlinerMangler Mangler(ObjCMethod->getMember(), isa<LoadInst>(FirstInst),
287+
UnpairedRelease);
278288
OutlinedName = Mangler.mangle();
279289
}
280290
return OutlinedName;
@@ -297,11 +307,10 @@ CanSILFunctionType BridgedProperty::getOutlinedFunctionType(SILModule &M) {
297307
SILParameterInfo(Load->getType().getASTType(),
298308
ParameterConvention::Indirect_In_Guaranteed));
299309
else
300-
Parameters.push_back(SILParameterInfo(cast<ObjCMethodInst>(FirstInst)
301-
->getOperand()
302-
->getType()
303-
.getASTType(),
304-
ParameterConvention::Direct_Unowned));
310+
Parameters.push_back(SILParameterInfo(
311+
cast<ObjCMethodInst>(FirstInst)->getOperand()->getType().getASTType(),
312+
UnpairedRelease ? ParameterConvention::Direct_Owned
313+
: ParameterConvention::Direct_Unowned));
305314
SmallVector<SILResultInfo, 4> Results;
306315

307316
Results.push_back(SILResultInfo(
@@ -415,6 +424,8 @@ BridgedProperty::outline(SILModule &M) {
415424
FirstInst->getOperand(0)->getType());
416425
auto *Arg = OutlinedEntryBB->getArgument(0);
417426
FirstInst->setOperand(0, Arg);
427+
if (UnpairedRelease)
428+
UnpairedRelease->setOperand(0, Arg);
418429
PropApply->setArgument(0, Arg);
419430
}
420431
Builder.setInsertionPoint(OldMergeBB);
@@ -625,12 +636,22 @@ bool BridgedProperty::matchMethodCall(SILBasicBlock::iterator It,
625636
assert(Release == &*It);
626637
}
627638

639+
ADVANCE_ITERATOR_OR_RETURN_FALSE(It);
640+
if (auto *dvi = dyn_cast<DestroyValueInst>(*&It)) {
641+
if (Load)
642+
return false;
643+
if (dvi->getOperand() != Instance)
644+
return false;
645+
UnpairedRelease = dvi;
646+
ADVANCE_ITERATOR_OR_RETURN_FALSE(It);
647+
}
648+
628649
// Don't outline in the outlined function.
629650
if (ObjCMethod->getFunction()->getName().equals(getOutlinedFunctionName()))
630651
return false;
631652

632-
// switch_enum %34 : $Optional<NSString>, case #Optional.some!enumelt: bb8, case #Optional.none!enumelt: bb9
633-
ADVANCE_ITERATOR_OR_RETURN_FALSE(It);
653+
// switch_enum %34 : $Optional<NSString>, case #Optional.some!enumelt: bb8,
654+
// case #Optional.none!enumelt: bb9
634655
return matchSwitch(switchInfo, &*It, PropApply);
635656
}
636657

test/SILOptimizer/outliner.swift

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ public class MyGizmo {
1818
// CHECK: [[A_FUN:%.*]] = function_ref @$sSo5GizmoC14stringPropertySSSgvgToTeab_
1919
// CHECK: apply [[A_FUN]]({{.*}}) : $@convention(thin) (@in_guaranteed Gizmo) -> @owned Optional<String>
2020
// CHECK-NOT: return
21-
// CHECK: [[P_FUN:%.*]] = function_ref @$sSo5GizmoC14stringPropertySSSgvgToTepb_
22-
// CHECK: apply [[P_FUN]]({{.*}}) : $@convention(thin) (Gizmo) -> @owned Optional<String>
21+
// CHECK: [[P_FUN:%.*]] = function_ref @$sSo5GizmoC14stringPropertySSSgvgToTeob_
22+
// CHECK: apply [[P_FUN]]({{.*}}) : $@convention(thin) (@owned Gizmo) -> @owned Optional<String>
2323
// CHECK: return
2424
// CHECK: } // end sil function '$s8outliner7MyGizmoC11usePropertyyyF'
2525
public func useProperty() {
@@ -66,26 +66,35 @@ public func testOutlining() {
6666
// CHECK: switch_enum [[RES]]
6767
// CHECK: } // end sil function '$s8outliner9dontCrash1ayyp_tF'
6868

69-
// CHECK-LABEL: sil shared [noinline] @$sSo5GizmoC14stringPropertySSSgvgToTeab_ : $@convention(thin) (@in_guaranteed Gizmo) -> @owned Optional<String>
70-
// CHECK: bb0(%0 : $*Gizmo):
71-
// CHECK: %1 = load %0 : $*Gizmo
72-
// CHECK: %2 = objc_method %1 : $Gizmo, #Gizmo.stringProperty!getter.foreign : (Gizmo) -> () -> String?
73-
// CHECK: %3 = apply %2(%1) : $@convention(objc_method) (Gizmo) -> @autoreleased Optional<NSString>
74-
// CHECK: switch_enum %3 : $Optional<NSString>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2
75-
// CHECK: bb1(%5 : $NSString):
76-
// CHECK: %6 = function_ref @$sSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
77-
// CHECK: %7 = metatype $@thin String.Type
78-
// CHECK: %8 = apply %6(%3, %7) : $@convention(method) (@guaranteed Optional<NSString>, @thin String.Type) -> @owned String
79-
// CHECK: release_value %3 : $Optional<NSString>
80-
// CHECK: %10 = enum $Optional<String>, #Optional.some!enumelt, %8 : $String
81-
// CHECK: br bb3(%10 : $Optional<String>)
82-
// CHECK: bb2:
83-
// CHECK: %12 = enum $Optional<String>, #Optional.none!enumelt
84-
// CHECK: br bb3(%12 : $Optional<String>)
85-
// CHECK: bb3(%14 : $Optional<String>):
86-
// CHECK: return %14 : $Optional<String>
69+
// CHECK-LABEL: sil shared [noinline] @$sSo5GizmoC14stringPropertySSSgvgToTeab_ : {{.*}} {
70+
// CHECK: {{bb[0-9]+}}([[ADDR:%[^,]+]] : $*Gizmo):
71+
// CHECK: [[INSTANCE:%[^,]+]] = load [[ADDR]]
72+
// CHECK: [[CONSUMING_OUTLINED_BRIDGED_PROPERTY:%[^,]+]] = function_ref @$sSo5GizmoC14stringPropertySSSgvgToTeob_
73+
// CHECK: strong_retain [[INSTANCE]]
74+
// CHECK: [[RETVAL:%[^,]+]] = apply [[CONSUMING_OUTLINED_BRIDGED_PROPERTY]]([[INSTANCE]])
75+
// CHECK: return [[RETVAL]]
8776
// CHECK: } // end sil function '$sSo5GizmoC14stringPropertySSSgvgToTeab_'
8877

78+
// CHECK-LABEL: sil shared [noinline] @$sSo5GizmoC14stringPropertySSSgvgToTeob_ : {{.*}} {
79+
// CHECK: {{bb[0-9]+}}([[INSTANCE:%[^,]+]] :
80+
// CHECK: [[GIZME_STRINGPROPERTY_GETTER:%[^,]+]] = objc_method [[INSTANCE]] : $Gizmo, #Gizmo.stringProperty!getter.foreign
81+
// CHECK: [[MAYBE_NSSTRING:%[^,]+]] = apply [[GIZME_STRINGPROPERTY_GETTER]]([[INSTANCE]])
82+
// CHECK: strong_release [[INSTANCE]]
83+
// CHECK: switch_enum [[MAYBE_NSSTRING]] : $Optional<NSString>, case #Optional.some!enumelt: [[SOME_BLOCK:bb[0-9]+]], case #Optional.none!enumelt: [[NONE_BLOCK:bb[0-9]+]]
84+
// CHECK: [[SOME_BLOCK]]([[REGISTER_5:%[^,]+]] : $NSString):
85+
// CHECK: [[STRING_FROM_NSSTRING:%[^,]+]] = function_ref @$sSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ
86+
// CHECK: [[STRING_TYPE:%[^,]+]] = metatype $@thin String.Type
87+
// CHECK: [[STRING:%[^,]+]] = apply [[STRING_FROM_NSSTRING]]([[MAYBE_NSSTRING]], [[STRING_TYPE]])
88+
// CHECK: release_value [[MAYBE_NSSTRING]]
89+
// CHECK: [[SOME_STRING:%[^,]+]] = enum $Optional<String>, #Optional.some!enumelt, [[STRING]]
90+
// CHECK: br [[EXIT:bb[0-9]+]]([[SOME_STRING]] : $Optional<String>)
91+
// CHECK: [[NONE_BLOCK]]:
92+
// CHECK: [[NONE_STRING:%[^,]+]] = enum $Optional<String>, #Optional.none!enumelt
93+
// CHECK: br [[EXIT]]([[NONE_STRING]] : $Optional<String>)
94+
// CHECK: [[EXIT]]([[MAYBE_STRING:%[^,]+]] :
95+
// CHECK: return [[MAYBE_STRING]]
96+
// CHECK-LABEL: } // end sil function '$sSo5GizmoC14stringPropertySSSgvgToTeob_'
97+
8998
// CHECK-LABEL: sil shared [noinline] @$sSo5GizmoC14stringPropertySSSgvgToTepb_ : $@convention(thin) (Gizmo) -> @owned Optional<String>
9099
// CHECK: bb0(%0 : $Gizmo):
91100
// CHECK: %1 = objc_method %0 : $Gizmo, #Gizmo.stringProperty!getter.foreign : (Gizmo) -> () -> String?

0 commit comments

Comments
 (0)