@@ -34,6 +34,21 @@ static bool isNoPayloadEnum(SILValue V) {
3434 return !EI->hasOperand ();
3535}
3636
37+ // / Returns true if V is a valid operand of a cast which preserves RC identity.
38+ // /
39+ // / V is a valid operand if it has a non-trivial type.
40+ // / RCIdentityAnalysis must not look through casts which cast from a trivial
41+ // / type, like a metatype, to something which is retainable, like an AnyObject.
42+ // / On some platforms such casts dynamically allocate a ref-counted box for the
43+ // / metatype. Naturally that is the place where a new rc-identity begins.
44+ // / Therefore such a cast is introducing a new rc identical object.
45+ // /
46+ // / If we would look through such a cast, ARC optimizations would get confused
47+ // / and might eliminate a retain of such an object completely.
48+ static bool isValidRCIdentityCastOperand (SILValue V, SILFunction *F) {
49+ return !V->getType ().isTrivial (*F);
50+ }
51+
3752// / RC identity is more than a guarantee that references refer to the same
3853// / object. It also means that reference counting operations on those references
3954// / have the same semantics. If the types on either side of a cast do not have
@@ -42,35 +57,26 @@ static bool isNoPayloadEnum(SILValue V) {
4257// / necessarily preserve RC identity because it may cast from a
4358// / reference-counted type to a non-reference counted type, or from a larger to
4459// / a smaller struct with fewer references.
45- static bool isRCIdentityPreservingCast (ValueKind Kind ) {
46- switch (Kind ) {
60+ static SILValue getRCIdentityPreservingCastOperand (SILValue V ) {
61+ switch (V-> getKind () ) {
4762 case ValueKind::UpcastInst:
4863 case ValueKind::UncheckedRefCastInst:
4964 case ValueKind::UnconditionalCheckedCastInst:
5065 case ValueKind::InitExistentialRefInst:
5166 case ValueKind::OpenExistentialRefInst:
5267 case ValueKind::RefToBridgeObjectInst:
5368 case ValueKind::BridgeObjectToRefInst:
54- case ValueKind::ConvertFunctionInst:
55- return true ;
69+ case ValueKind::ConvertFunctionInst: {
70+ auto *inst = cast<SingleValueInstruction>(V);
71+ SILValue castOp = inst->getOperand (0 );
72+ if (isValidRCIdentityCastOperand (castOp, inst->getFunction ()))
73+ return castOp;
74+ break ;
75+ }
5676 default :
57- return false ;
77+ break ;
5878 }
59- }
60-
61- // / Returns a null SILValue if V has a trivial type, otherwise returns V.
62- // /
63- // / RCIdentityAnalysis must not look through casts which cast from a trivial
64- // / type, like a metatype, to something which is retainable, like an AnyObject.
65- // / On some platforms such casts dynamically allocate a ref-counted box for the
66- // / metatype.
67- // / Now, if the RCRoot of such an AnyObject would be a trivial type, ARC
68- // / optimizations get confused and might eliminate a retain of such an object
69- // / completely.
70- static SILValue noTrivialType (SILValue V, SILFunction *F) {
71- if (V->getType ().isTrivial (*F))
72- return SILValue ();
73- return V;
79+ return SILValue ();
7480}
7581
7682// ===----------------------------------------------------------------------===//
@@ -79,10 +85,8 @@ static SILValue noTrivialType(SILValue V, SILFunction *F) {
7985
8086static SILValue stripRCIdentityPreservingInsts (SILValue V) {
8187 // First strip off RC identity preserving casts.
82- if (isRCIdentityPreservingCast (V->getKind ())) {
83- auto *inst = cast<SingleValueInstruction>(V);
84- return noTrivialType (inst->getOperand (0 ), inst->getFunction ());
85- }
88+ if (SILValue castOp = getRCIdentityPreservingCastOperand (V))
89+ return castOp;
8690
8791 // Then if we have a struct_extract that is extracting a non-trivial member
8892 // from a struct with no other non-trivial members, a ref count operation on
@@ -133,9 +137,14 @@ static SILValue stripRCIdentityPreservingInsts(SILValue V) {
133137 // since we will only visit it twice if we go around a back edge due to a
134138 // different SILArgument that is actually being used for its phi node like
135139 // purposes.
136- if (auto *A = dyn_cast<SILPhiArgument>(V))
137- if (SILValue Result = A->getSingleTerminatorOperand ())
138- return noTrivialType (Result, A->getFunction ());
140+ if (auto *A = dyn_cast<SILPhiArgument>(V)) {
141+ if (SILValue Result = A->getSingleTerminatorOperand ()) {
142+ // In case the terminator is a conditional cast, Result is the source of
143+ // the cast.
144+ if (isValidRCIdentityCastOperand (Result, A->getFunction ()))
145+ return Result;
146+ }
147+ }
139148
140149 return SILValue ();
141150}
@@ -339,7 +348,7 @@ SILValue RCIdentityFunctionInfo::stripRCIdentityPreservingArgs(SILValue V,
339348
340349 unsigned IVListSize = IncomingValues.size ();
341350 if (IVListSize == 1 &&
342- !noTrivialType (IncomingValues[0 ].second , A->getFunction ()))
351+ !isValidRCIdentityCastOperand (IncomingValues[0 ].second , A->getFunction ()))
343352 return SILValue ();
344353
345354 assert (IVListSize != 1 && " Should have been handled in "
0 commit comments