@@ -1597,6 +1597,7 @@ optimizeBridgedObjCToSwiftCast(SILInstruction *Inst,
1597
1597
SILInstruction *
1598
1598
CastOptimizer::
1599
1599
optimizeBridgedSwiftToObjCCast (SILInstruction *Inst,
1600
+ CastConsumptionKind ConsumptionKind,
1600
1601
bool isConditional,
1601
1602
SILValue Src,
1602
1603
SILValue Dest,
@@ -1679,16 +1680,77 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
1679
1680
Src = Builder.createLoad (Loc, Src);
1680
1681
}
1681
1682
1682
- if (ParamTypes[0 ].getConvention () == ParameterConvention::Direct_Guaranteed)
1683
+ // Compensate different owning conventions of the replaced cast instruction
1684
+ // and the inserted convertion function.
1685
+ bool needRetainBeforeCall = false ;
1686
+ bool needReleaseAfterCall = false ;
1687
+ bool needReleaseInSucc = false ;
1688
+ switch (ParamTypes[0 ].getConvention ()) {
1689
+ case ParameterConvention::Direct_Guaranteed:
1690
+ switch (ConsumptionKind) {
1691
+ case CastConsumptionKind::TakeAlways:
1692
+ needReleaseAfterCall = true ;
1693
+ break ;
1694
+ case CastConsumptionKind::TakeOnSuccess:
1695
+ needReleaseInSucc = true ;
1696
+ break ;
1697
+ case CastConsumptionKind::CopyOnSuccess:
1698
+ // Conservatively insert a retain/release pair around the conversion
1699
+ // function because the conversion function could decrement the
1700
+ // (global) reference count of the source object.
1701
+ //
1702
+ // %src = load %global_var
1703
+ // apply %conversion_func(@guaranteed %src)
1704
+ //
1705
+ // sil conversion_func {
1706
+ // %old_value = load %global_var
1707
+ // store %something_else, %global_var
1708
+ // strong_release %old_value
1709
+ // }
1710
+ needRetainBeforeCall = true ;
1711
+ needReleaseAfterCall = true ;
1712
+ break ;
1713
+ }
1714
+ break ;
1715
+ case ParameterConvention::Direct_Owned:
1716
+ // The Direct_Owned case is only handled for completeness. Currently this
1717
+ // cannot appear, because the _bridgeToObjectiveC protocol witness method
1718
+ // always receives the this pointer (= the source) as guaranteed.
1719
+ switch (ConsumptionKind) {
1720
+ case CastConsumptionKind::TakeAlways:
1721
+ break ;
1722
+ case CastConsumptionKind::TakeOnSuccess:
1723
+ needRetainBeforeCall = true ;
1724
+ needReleaseInSucc = true ;
1725
+ break ;
1726
+ case CastConsumptionKind::CopyOnSuccess:
1727
+ needRetainBeforeCall = true ;
1728
+ break ;
1729
+ }
1730
+ break ;
1731
+ case ParameterConvention::Direct_Unowned:
1732
+ break ;
1733
+ case ParameterConvention::Indirect_In:
1734
+ case ParameterConvention::Indirect_Inout:
1735
+ case ParameterConvention::Indirect_InoutAliasable:
1736
+ case ParameterConvention::Indirect_In_Guaranteed:
1737
+ case ParameterConvention::Direct_Deallocating:
1738
+ llvm_unreachable (" unsupported convention for bridging conversion" );
1739
+ }
1740
+
1741
+ if (needRetainBeforeCall)
1683
1742
Builder.createRetainValue (Loc, Src, Atomicity::Atomic);
1684
1743
1685
1744
// Generate a code to invoke the bridging function.
1686
1745
auto *NewAI = Builder.createApply (Loc, FnRef, SubstFnTy, ResultTy, Subs, Src,
1687
1746
false );
1688
1747
1689
- if (ParamTypes[ 0 ]. getConvention () == ParameterConvention::Direct_Guaranteed)
1748
+ if (needReleaseAfterCall) {
1690
1749
Builder.createReleaseValue (Loc, Src, Atomicity::Atomic);
1691
-
1750
+ } else if (needReleaseInSucc) {
1751
+ SILBuilder SuccBuilder (SuccessBB->begin ());
1752
+ SuccBuilder.createReleaseValue (Loc, Src, Atomicity::Atomic);
1753
+ }
1692
1754
SILInstruction *NewI = NewAI;
1693
1755
1694
1756
if (Dest) {
@@ -1721,6 +1783,7 @@ optimizeBridgedSwiftToObjCCast(SILInstruction *Inst,
1721
1783
SILInstruction *
1722
1784
CastOptimizer::
1723
1785
optimizeBridgedCasts (SILInstruction *Inst,
1786
+ CastConsumptionKind ConsumptionKind,
1724
1787
bool isConditional,
1725
1788
SILValue Src,
1726
1789
SILValue Dest,
@@ -1786,7 +1849,8 @@ optimizeBridgedCasts(SILInstruction *Inst,
1786
1849
target, BridgedSourceTy, BridgedTargetTy, SuccessBB, FailureBB);
1787
1850
} else {
1788
1851
// This is a Swift to ObjC cast
1789
- return optimizeBridgedSwiftToObjCCast (Inst, isConditional, Src, Dest, source,
1852
+ return optimizeBridgedSwiftToObjCCast (Inst, ConsumptionKind,
1853
+ isConditional, Src, Dest, source,
1790
1854
target, BridgedSourceTy, BridgedTargetTy, SuccessBB, FailureBB);
1791
1855
}
1792
1856
}
@@ -1863,7 +1927,8 @@ simplifyCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *Inst) {
1863
1927
// To apply the bridged optimizations, we should
1864
1928
// ensure that types are not existential,
1865
1929
// and that not both types are classes.
1866
- BridgedI = optimizeBridgedCasts (Inst, true , Src, Dest, SourceType,
1930
+ BridgedI = optimizeBridgedCasts (Inst, Inst->getConsumptionKind (),
1931
+ true , Src, Dest, SourceType,
1867
1932
TargetType, SuccessBB, FailureBB);
1868
1933
1869
1934
if (!BridgedI) {
@@ -1975,7 +2040,8 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
1975
2040
auto Src = Inst->getOperand ();
1976
2041
auto Dest = SILValue ();
1977
2042
// To apply the bridged casts optimizations.
1978
- auto BridgedI = optimizeBridgedCasts (Inst, false , Src, Dest, SourceType,
2043
+ auto BridgedI = optimizeBridgedCasts (Inst,
2044
+ CastConsumptionKind::CopyOnSuccess, false , Src, Dest, SourceType,
1979
2045
TargetType, nullptr , nullptr );
1980
2046
1981
2047
if (BridgedI) {
@@ -2290,8 +2356,9 @@ optimizeUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *Inst) {
2290
2356
auto SourceType = LoweredSourceType.getSwiftRValueType ();
2291
2357
auto TargetType = LoweredTargetType.getSwiftRValueType ();
2292
2358
auto Src = Inst->getOperand ();
2293
- auto NewI = optimizeBridgedCasts (Inst, false , Src, SILValue (), SourceType,
2294
- TargetType, nullptr , nullptr );
2359
+ auto NewI = optimizeBridgedCasts (Inst, CastConsumptionKind::CopyOnSuccess,
2360
+ false , Src, SILValue (), SourceType,
2361
+ TargetType, nullptr , nullptr );
2295
2362
if (NewI) {
2296
2363
ReplaceInstUsesAction (Inst, NewI);
2297
2364
EraseInstAction (Inst);
@@ -2406,14 +2473,25 @@ optimizeUnconditionalCheckedCastAddrInst(UnconditionalCheckedCastAddrInst *Inst)
2406
2473
}
2407
2474
2408
2475
if (ResultNotUsed) {
2476
+ switch (Inst->getConsumptionKind ()) {
2477
+ case CastConsumptionKind::TakeAlways:
2478
+ case CastConsumptionKind::TakeOnSuccess: {
2479
+ SILBuilder B (Inst);
2480
+ B.createDestroyAddr (Inst->getLoc (), Inst->getSrc ());
2481
+ break ;
2482
+ }
2483
+ case CastConsumptionKind::CopyOnSuccess:
2484
+ break ;
2485
+ }
2409
2486
EraseInstAction (Inst);
2410
2487
WillSucceedAction ();
2411
2488
return nullptr ;
2412
2489
}
2413
2490
2414
2491
// Try to apply the bridged casts optimizations
2415
- auto NewI = optimizeBridgedCasts (Inst, false , Src, Dest, SourceType,
2416
- TargetType, nullptr , nullptr );
2492
+ auto NewI = optimizeBridgedCasts (Inst, Inst->getConsumptionKind (),
2493
+ false , Src, Dest, SourceType,
2494
+ TargetType, nullptr , nullptr );
2417
2495
if (NewI) {
2418
2496
WillSucceedAction ();
2419
2497
return nullptr ;
0 commit comments