@@ -50,6 +50,7 @@ class OutlinerMangler : public Mangle::ASTMangler {
50
50
// / The kind of method bridged.
51
51
enum MethodKind : unsigned {
52
52
BridgedProperty,
53
+ BridgedProperty_Consuming,
53
54
BridgedPropertyAddress,
54
55
BridgedMethod,
55
56
};
@@ -69,10 +70,12 @@ class OutlinerMangler : public Mangle::ASTMangler {
69
70
Kind(BridgedMethod), IsReturnBridged(ReturnBridged) {}
70
71
71
72
// / Create an mangler for an outlined bridged property.
72
- OutlinerMangler (SILDeclRef Method, bool IsAddress)
73
+ OutlinerMangler (SILDeclRef Method, bool IsAddress, bool ConsumesValue )
73
74
: IsParameterBridged(nullptr ), IsParameterGuaranteed(nullptr ),
74
75
MethodDecl(Method),
75
- Kind(IsAddress ? BridgedPropertyAddress : BridgedProperty),
76
+ Kind(IsAddress ? BridgedPropertyAddress
77
+ : (ConsumesValue ? BridgedProperty_Consuming
78
+ : BridgedProperty)),
76
79
IsReturnBridged(true ) {}
77
80
78
81
std::string mangle ();
@@ -82,6 +85,8 @@ class OutlinerMangler : public Mangle::ASTMangler {
82
85
switch (Kind) {
83
86
case BridgedProperty:
84
87
return ' p' ;
88
+ case BridgedProperty_Consuming:
89
+ return ' o' ;
85
90
case BridgedPropertyAddress:
86
91
return ' a' ;
87
92
case BridgedMethod:
@@ -234,6 +239,9 @@ class BridgedProperty : public OutlinePattern {
234
239
ObjCMethodInst *ObjCMethod;
235
240
SILInstruction *Release;
236
241
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.
237
245
238
246
public:
239
247
bool matchInstSequence (SILBasicBlock::iterator I) override ;
@@ -256,7 +264,7 @@ class BridgedProperty : public OutlinePattern {
256
264
std::string getOutlinedFunctionName () override ;
257
265
258
266
private:
259
- bool matchMethodCall (SILBasicBlock::iterator);
267
+ bool matchMethodCall (SILBasicBlock::iterator, LoadInst * );
260
268
CanSILFunctionType getOutlinedFunctionType (SILModule &M);
261
269
void clearState ();
262
270
};
@@ -269,12 +277,14 @@ void BridgedProperty::clearState() {
269
277
ObjCMethod = nullptr ;
270
278
Release = nullptr ;
271
279
PropApply = nullptr ;
280
+ UnpairedRelease = nullptr ;
272
281
OutlinedName.clear ();
273
282
}
274
283
275
284
std::string BridgedProperty::getOutlinedFunctionName () {
276
285
if (OutlinedName.empty ()) {
277
- OutlinerMangler Mangler (ObjCMethod->getMember (), isa<LoadInst>(FirstInst));
286
+ OutlinerMangler Mangler (ObjCMethod->getMember (), isa<LoadInst>(FirstInst),
287
+ UnpairedRelease);
278
288
OutlinedName = Mangler.mangle ();
279
289
}
280
290
return OutlinedName;
@@ -297,11 +307,10 @@ CanSILFunctionType BridgedProperty::getOutlinedFunctionType(SILModule &M) {
297
307
SILParameterInfo (Load->getType ().getASTType (),
298
308
ParameterConvention::Indirect_In_Guaranteed));
299
309
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));
305
314
SmallVector<SILResultInfo, 4 > Results;
306
315
307
316
Results.push_back (SILResultInfo (
@@ -415,6 +424,8 @@ BridgedProperty::outline(SILModule &M) {
415
424
FirstInst->getOperand (0 )->getType ());
416
425
auto *Arg = OutlinedEntryBB->getArgument (0 );
417
426
FirstInst->setOperand (0 , Arg);
427
+ if (UnpairedRelease)
428
+ UnpairedRelease->setOperand (0 , Arg);
418
429
PropApply->setArgument (0 , Arg);
419
430
}
420
431
Builder.setInsertionPoint (OldMergeBB);
@@ -546,7 +557,8 @@ static bool matchSwitch(SwitchInfo &SI, SILInstruction *Inst,
546
557
return true ;
547
558
}
548
559
549
- bool BridgedProperty::matchMethodCall (SILBasicBlock::iterator It) {
560
+ bool BridgedProperty::matchMethodCall (SILBasicBlock::iterator It,
561
+ LoadInst *Load) {
550
562
// Matches:
551
563
// %33 = objc_method %31 : $UITextField, #UITextField.text!getter.foreign : (UITextField) -> () -> String?, $@convention(objc_method) (UITextField) -> @autoreleased Optional<NSString>
552
564
// %34 = apply %33(%31) : $@convention(objc_method) (UITextField) -> @autoreleased Optional<NSString>
@@ -578,10 +590,6 @@ bool BridgedProperty::matchMethodCall(SILBasicBlock::iterator It) {
578
590
ObjCMethod->getType ().castTo <SILFunctionType>()->hasOpenedExistential ())
579
591
return false ;
580
592
581
- // Don't outline in the outlined function.
582
- if (ObjCMethod->getFunction ()->getName ().equals (getOutlinedFunctionName ()))
583
- return false ;
584
-
585
593
// %34 = apply %33(%31) : $@convention(objc_method) (UITextField) -> @autoreleased Optional<NSString>
586
594
ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
587
595
PropApply = dyn_cast<ApplyInst>(It);
@@ -590,8 +598,60 @@ bool BridgedProperty::matchMethodCall(SILBasicBlock::iterator It) {
590
598
PropApply->getArgument (0 ) != Instance || !PropApply->hasOneUse ())
591
599
return false ;
592
600
593
- // switch_enum %34 : $Optional<NSString>, case #Optional.some!enumelt: bb8, case #Optional.none!enumelt: bb9
601
+ if (Load) {
602
+ // In OSSA, there will be a destroy_value matching the earlier load [copy].
603
+ // In non-ossa, there will be a release matching the earlier retain. The
604
+ // only user of the retained value is the unowned objective-c method
605
+ // consumer.
606
+ unsigned NumUses = 0 ;
607
+ Release = nullptr ;
608
+ bool hasOwnership = Load->getFunction ()->hasOwnership ();
609
+ for (auto *Use : Load->getUses ()) {
610
+ ++NumUses;
611
+ SILInstruction *R;
612
+ if (hasOwnership) {
613
+ R = dyn_cast<DestroyValueInst>(Use->getUser ());
614
+ } else {
615
+ R = dyn_cast<StrongReleaseInst>(Use->getUser ());
616
+ }
617
+ if (R) {
618
+ if (!Release) {
619
+ Release = R;
620
+ } else {
621
+ Release = nullptr ;
622
+ break ;
623
+ }
624
+ }
625
+ }
626
+ if (!Release)
627
+ return false ;
628
+ if (hasOwnership) {
629
+ if (NumUses != 3 )
630
+ return false ;
631
+ } else {
632
+ if (NumUses != 4 )
633
+ return false ;
634
+ }
635
+ ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
636
+ assert (Release == &*It);
637
+ }
638
+
594
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
+
649
+ // Don't outline in the outlined function.
650
+ if (ObjCMethod->getFunction ()->getName ().equals (getOutlinedFunctionName ()))
651
+ return false ;
652
+
653
+ // switch_enum %34 : $Optional<NSString>, case #Optional.some!enumelt: bb8,
654
+ // case #Optional.none!enumelt: bb9
595
655
return matchSwitch (switchInfo, &*It, PropApply);
596
656
}
597
657
@@ -642,6 +702,7 @@ bool BridgedProperty::matchInstSequence(SILBasicBlock::iterator It) {
642
702
if (Load->getFunction ()->hasOwnership ()) {
643
703
if (Load->getOwnershipQualifier () != LoadOwnershipQualifier::Copy)
644
704
return false ;
705
+ ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
645
706
} else {
646
707
// strong_retain %31 : $UITextField
647
708
ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
@@ -652,44 +713,9 @@ bool BridgedProperty::matchInstSequence(SILBasicBlock::iterator It) {
652
713
}
653
714
}
654
715
655
- if (!matchMethodCall (It))
716
+ if (!matchMethodCall (It, Load ))
656
717
return false ;
657
718
658
- if (Load) {
659
- // In OSSA, there will be a destroy_value matching the earlier load [copy].
660
- // In non-ossa, there will be a release matching the earlier retain. The
661
- // only user of the retained value is the unowned objective-c method
662
- // consumer.
663
- unsigned NumUses = 0 ;
664
- Release = nullptr ;
665
- bool hasOwnership = Load->getFunction ()->hasOwnership ();
666
- for (auto *Use : Load->getUses ()) {
667
- ++NumUses;
668
- SILInstruction *R;
669
- if (hasOwnership) {
670
- R = dyn_cast<DestroyValueInst>(Use->getUser ());
671
- } else {
672
- R = dyn_cast<StrongReleaseInst>(Use->getUser ());
673
- }
674
- if (R) {
675
- if (!Release) {
676
- Release = R;
677
- } else {
678
- Release = nullptr ;
679
- break ;
680
- }
681
- }
682
- }
683
- if (!Release)
684
- return false ;
685
- if (hasOwnership) {
686
- if (NumUses != 3 )
687
- return false ;
688
- } else {
689
- if (NumUses != 4 )
690
- return false ;
691
- }
692
- }
693
719
return true ;
694
720
}
695
721
@@ -1274,8 +1300,6 @@ namespace {
1274
1300
class OutlinePatterns {
1275
1301
BridgedProperty BridgedPropertyPattern;
1276
1302
ObjCMethodCall ObjCMethodCallPattern;
1277
- llvm::DenseMap<CanType, SILDeclRef> BridgeToObjectiveCCache;
1278
- llvm::DenseMap<CanType, SILDeclRef> BridgeFromObjectiveCache;
1279
1303
1280
1304
public:
1281
1305
// / Try matching an outlineable pattern from the current instruction.
0 commit comments