@@ -224,7 +224,7 @@ class BridgedProperty : public OutlinePattern {
224
224
SILBasicBlock *StartBB;
225
225
SwitchInfo switchInfo;
226
226
ObjCMethodInst *ObjCMethod;
227
- StrongReleaseInst *Release;
227
+ SILInstruction *Release;
228
228
ApplyInst *PropApply;
229
229
230
230
public:
@@ -505,11 +505,18 @@ static bool matchSwitch(SwitchInfo &SI, SILInstruction *Inst,
505
505
return false ;
506
506
507
507
if (numSomeEnumUses == 2 ) {
508
- // release_value %38 : $Optional<NSString>
508
+ // [ release_value | destroy_value] %38 : $Optional<NSString>
509
509
ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
510
- auto *RVI = dyn_cast<ReleaseValueInst>(It);
511
- if (!RVI || RVI->getOperand () != SomeEnum)
512
- return false ;
510
+ bool hasOwnership = It->getFunction ()->hasOwnership ();
511
+ if (hasOwnership) {
512
+ auto *DVI = dyn_cast<DestroyValueInst>(It);
513
+ if (!DVI || DVI->getOperand () != SomeEnum)
514
+ return false ;
515
+ } else {
516
+ auto *RVI = dyn_cast<ReleaseValueInst>(It);
517
+ if (!RVI || RVI->getOperand () != SomeEnum)
518
+ return false ;
519
+ }
513
520
}
514
521
515
522
// br bb10(%41 : $Optional<String>)
@@ -578,7 +585,7 @@ bool BridgedProperty::matchMethodCall(SILBasicBlock::iterator It) {
578
585
bool BridgedProperty::matchInstSequence (SILBasicBlock::iterator It) {
579
586
// Matches:
580
587
// [ optionally:
581
- // %31 = load %30 : $*UITextField
588
+ // %31 = load %30 : $*UITextField or %31 = load [copy] %30 : $*UITextField
582
589
// strong_retain %31 : $UITextField
583
590
// ]
584
591
// %33 = objc_method %31 : $UITextField, #UITextField.text!getter.foreign : (UITextField) -> () -> String?, $@convention(objc_method) (UITextField) -> @autoreleased Optional<NSString>
@@ -619,25 +626,39 @@ bool BridgedProperty::matchInstSequence(SILBasicBlock::iterator It) {
619
626
StartBB = FirstInst->getParent ();
620
627
621
628
if (Load) {
622
- // strong_retain %31 : $UITextField
623
- ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
624
- auto *Retain = dyn_cast<StrongRetainInst>(It);
625
- if (!Retain || Retain->getOperand () != Load)
626
- return false ;
627
- ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
629
+ if (Load->getFunction ()->hasOwnership ()) {
630
+ if (Load->getOwnershipQualifier () != LoadOwnershipQualifier::Copy)
631
+ return false ;
632
+ } else {
633
+ // strong_retain %31 : $UITextField
634
+ ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
635
+ auto *Retain = dyn_cast<StrongRetainInst>(It);
636
+ if (!Retain || Retain->getOperand () != Load)
637
+ return false ;
638
+ ADVANCE_ITERATOR_OR_RETURN_FALSE (It);
639
+ }
628
640
}
629
641
630
642
if (!matchMethodCall (It))
631
643
return false ;
632
644
633
645
if (Load) {
634
- // There will be a release matching the earlier retain. The only user of the
635
- // retained value is the unowned objective-c method consumer.
646
+ // In OSSA, there will be a destroy_value matching the earlier load [copy].
647
+ // In non-ossa, there will be a release matching the earlier retain. The
648
+ // only user of the retained value is the unowned objective-c method
649
+ // consumer.
636
650
unsigned NumUses = 0 ;
637
651
Release = nullptr ;
652
+ bool hasOwnership = Load->getFunction ()->hasOwnership ();
638
653
for (auto *Use : Load->getUses ()) {
639
654
++NumUses;
640
- if (auto *R = dyn_cast<StrongReleaseInst>(Use->getUser ())) {
655
+ SILInstruction *R;
656
+ if (hasOwnership) {
657
+ R = dyn_cast<DestroyValueInst>(Use->getUser ());
658
+ } else {
659
+ R = dyn_cast<StrongReleaseInst>(Use->getUser ());
660
+ }
661
+ if (R) {
641
662
if (!Release) {
642
663
Release = R;
643
664
} else {
@@ -646,8 +667,15 @@ bool BridgedProperty::matchInstSequence(SILBasicBlock::iterator It) {
646
667
}
647
668
}
648
669
}
649
- if (!Release || NumUses != 4 )
670
+ if (!Release)
650
671
return false ;
672
+ if (hasOwnership) {
673
+ if (NumUses != 3 )
674
+ return false ;
675
+ } else {
676
+ if (NumUses != 4 )
677
+ return false ;
678
+ }
651
679
}
652
680
return true ;
653
681
}
@@ -676,16 +704,18 @@ class BridgedArgument {
676
704
ApplyInst *BridgeCall;
677
705
EnumInst *OptionalResult;
678
706
SILValue BridgedValue;
679
- ReleaseValueInst *ReleaseAfterBridge;
680
- ReleaseValueInst *ReleaseArgAfterCall;
707
+ SILInstruction *ReleaseAfterBridge;
708
+ SILInstruction *ReleaseArgAfterCall;
681
709
unsigned Idx = 0 ;
682
710
683
711
// Matched bridged argument.
684
712
BridgedArgument (unsigned Idx, FunctionRefInst *F, ApplyInst *A, EnumInst *E,
685
- ReleaseValueInst *R0, ReleaseValueInst *R1)
713
+ SILInstruction *R0, SILInstruction *R1)
686
714
: BridgeFun(F), BridgeCall(A), OptionalResult(E),
687
715
BridgedValue (FullApplySite(A).getSelfArgument()),
688
- ReleaseAfterBridge(R0), ReleaseArgAfterCall(R1), Idx(Idx) {}
716
+ ReleaseAfterBridge(R0), ReleaseArgAfterCall(R1), Idx(Idx) {
717
+ assert (!R0 || isa<ReleaseValueInst>(R0) || isa<DestroyValueInst>(R0));
718
+ }
689
719
690
720
// / Invalid argument constructor.
691
721
BridgedArgument ()
@@ -726,7 +756,7 @@ void BridgedArgument::transferTo(SILValue BridgedValue,
726
756
DestBB->moveTo (SILBasicBlock::iterator (BridgedCall), OptionalResult);
727
757
if (ReleaseAfterBridge) {
728
758
DestBB->moveTo (SILBasicBlock::iterator (BridgedCall), ReleaseAfterBridge);
729
- ReleaseAfterBridge->setOperand (BridgedValue);
759
+ ReleaseAfterBridge->setOperand (0 , BridgedValue);
730
760
}
731
761
auto AfterCall = std::next (SILBasicBlock::iterator (BridgedCall));
732
762
DestBB->moveTo (SILBasicBlock::iterator (AfterCall), ReleaseArgAfterCall);
@@ -741,13 +771,20 @@ void BridgedArgument::eraseFromParent() {
741
771
BridgeFun->eraseFromParent ();
742
772
}
743
773
744
- static ReleaseValueInst *findReleaseOf (SILValue releasedValue,
745
- SILBasicBlock::iterator from,
746
- SILBasicBlock::iterator to) {
774
+ static SILInstruction *findReleaseOf (SILValue releasedValue,
775
+ SILBasicBlock::iterator from,
776
+ SILBasicBlock::iterator to) {
777
+ bool hasOwnership = releasedValue->getFunction ()->hasOwnership ();
747
778
while (from != to) {
748
- auto release = dyn_cast<ReleaseValueInst>(&*from);
749
- if (release && release->getOperand () == releasedValue)
750
- return release;
779
+ if (hasOwnership) {
780
+ auto destroy = dyn_cast<DestroyValueInst>(&*from);
781
+ if (destroy && destroy->getOperand () == releasedValue)
782
+ return destroy;
783
+ } else {
784
+ auto release = dyn_cast<ReleaseValueInst>(&*from);
785
+ if (release && release->getOperand () == releasedValue)
786
+ return release;
787
+ }
751
788
++from;
752
789
}
753
790
return nullptr ;
@@ -757,14 +794,13 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
757
794
ApplyInst *AI) {
758
795
// Match
759
796
// %15 = function_ref @$SSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF
760
- // %16 = apply %15(%14) :
761
- // $@convention(method) (@guaranteed String) -> @owned NSString
797
+ // %16 = apply %15(%14) : $@convention(method) (@guaranteed String) -> @owned NSString
762
798
// %17 = enum $Optional<NSString>, #Optional.some!enumelt, %16 : $NSString
763
- // release_value %14 : $String
799
+ // [ release_value | destroy_value] %14 : $String
764
800
// ...
765
- // apply %objcMethod(%17, ...) : $@convention(objc_method) (Optional<NSString> ...) ->
801
+ // apply %objcMethod(%17, ...) : $@convention(objc_method) (Optional<NSString>...) ->
766
802
// release_value ...
767
- // release_value %17 : $Optional<NSString>
803
+ // [ release_value | destroy_value] %17 : $Optional<NSString>
768
804
//
769
805
auto *Enum = dyn_cast<EnumInst>(Arg);
770
806
if (!Enum || !Enum->hasOperand ())
@@ -795,10 +831,15 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
795
831
// value.
796
832
if (Enum->getParent () != AI->getParent ())
797
833
return BridgedArgument ();
798
- auto *BridgedValueRelease = dyn_cast_or_null<ReleaseValueInst>(
834
+
835
+ bool hasOwnership = AI->getFunction ()->hasOwnership ();
836
+ auto *BridgedValueRelease =
799
837
findReleaseOf (BridgedValue, std::next (SILBasicBlock::iterator (Enum)),
800
- SILBasicBlock::iterator (AI)));
801
- if (BridgedValueRelease && BridgedValueRelease->getOperand () != BridgedValue)
838
+ SILBasicBlock::iterator (AI));
839
+ assert (!BridgedValueRelease ||
840
+ (hasOwnership && isa<DestroyValueInst>(BridgedValueRelease)) ||
841
+ isa<ReleaseValueInst>(BridgedValueRelease));
842
+ if (BridgedValueRelease && BridgedValueRelease->getOperand (0 ) != BridgedValue)
802
843
return BridgedArgument ();
803
844
804
845
if (SILBasicBlock::iterator (BridgeCall) == BridgeCall->getParent ()->begin ())
@@ -808,7 +849,7 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
808
849
if (!FunRef || !FunRef->hasOneUse () || BridgeCall->getCallee () != FunRef)
809
850
return BridgedArgument ();
810
851
811
- ReleaseValueInst *ReleaseAfter = nullptr ;
852
+ SILInstruction *ReleaseAfter = nullptr ;
812
853
for (auto *Use : Enum->getUses ()) {
813
854
if (Use->getUser () == AI)
814
855
continue ;
@@ -817,7 +858,11 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
817
858
if (ReleaseAfter)
818
859
return BridgedArgument ();
819
860
820
- ReleaseAfter = dyn_cast<ReleaseValueInst>(Use->getUser ());
861
+ if (hasOwnership) {
862
+ ReleaseAfter = dyn_cast<DestroyValueInst>(Use->getUser ());
863
+ } else {
864
+ ReleaseAfter = dyn_cast<ReleaseValueInst>(Use->getUser ());
865
+ }
821
866
if (!ReleaseAfter)
822
867
return BridgedArgument ();
823
868
}
@@ -838,7 +883,7 @@ BridgedArgument BridgedArgument::match(unsigned ArgIdx, SILValue Arg,
838
883
}
839
884
840
885
namespace {
841
- // Match the return value briding pattern.
886
+ // Match the return value bridging pattern.
842
887
// switch_enum %20 : $Optional<NSString>, case #O.some: bb1, case #O.none: bb2
843
888
//
844
889
// bb1(%23 : $NSString):
@@ -1274,10 +1319,6 @@ class Outliner : public SILFunctionTransform {
1274
1319
void run () override {
1275
1320
auto *Fun = getFunction ();
1276
1321
1277
- // We do not support [ossa] now.
1278
- if (Fun->hasOwnership ())
1279
- return ;
1280
-
1281
1322
// Only outline if we optimize for size.
1282
1323
if (!Fun->optimizeForSize ())
1283
1324
return ;
0 commit comments