@@ -79,6 +79,63 @@ static SubstitutionMap lookupBridgeToObjCProtocolSubs(SILModule &mod,
7979// / _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
8080// / instance into a corresponding Swift type, conforming to
8181// / _ObjectiveCBridgeable.
82+ // /
83+ // / Control Flow Modification Model
84+ // / ===============================
85+ // /
86+ // / NOTE: In the following we assume that our src type is not address only. We
87+ // / do not support optimizing such source types today.
88+ // /
89+ // / Unconditional Casts
90+ // / -------------------
91+ // /
92+ // / In the case of unconditional casts, we do not touch the CFG at all. We
93+ // / perform the following optimizations:
94+ // /
95+ // / 1. If the bridged type and the src type equal, we replace the cast with the
96+ // / apply.
97+ // /
98+ // / 2. If src is an address and bridged type has the matching object type to
99+ // / src, just load the value and again replace the cast with the apply.
100+ // /
101+ // / 3. If src is an address and after loading still doesn't match bridged type,
102+ // / insert an unconditional_checked_cast before calling the apply.
103+ // /
104+ // / Conditional Casts
105+ // / -----------------
106+ // /
107+ // / In the case of a conditional const (i.e. checked_cast_addr_br), we transform
108+ // / the following CFG:
109+ // /
110+ // / ```
111+ // / InstBlock (checked_cast_addr_br) -> FailureBB -> FailureSucc
112+ // / \
113+ /// \----------------------------> SuccessBB -> SuccessSucc
114+ // / ```
115+ // /
116+ // / to a CFG of the following form:
117+ // /
118+ // / ```
119+ // / InstBlock (checked_cast_br) -> CastFailBB -> FailureBB -> FailureSucc
120+ // / | ^
121+ // / \-> CastSuccessBB (bridge call + switch) --|
122+ // / |
123+ // / \-> BridgeSuccessBB -> SuccessBB -> SuccessSucc
124+ // / ```
125+ // /
126+ // / NOTE: That if the underlying src type matches the type of the underlying
127+ // / bridge source object, we can omit the initial checked_cast_br and just load
128+ // / the value + branch to the CastSuccessBB. This results instead in the
129+ // / following CFG:
130+ // /
131+ // / ```
132+ // / InstBlock (br) FailureBB -> FailureSucc
133+ // / | ^
134+ // / \-> CastSuccessBB (bridge call + switch) --|
135+ // / |
136+ // / \-> BridgeSuccessBB -> SuccessBB -> SuccessSucc
137+ // / ```
138+ // /
82139SILInstruction *
83140CastOptimizer::optimizeBridgedObjCToSwiftCast (SILDynamicCastInst dynamicCast) {
84141 auto kind = dynamicCast.getKind ();
@@ -99,6 +156,7 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
99156 }
100157
101158 SILValue src = dynamicCast.getSource ();
159+
102160 // Check if we have a source type that is address only. We do not support that
103161 // today.
104162 if (src->getType ().isAddressOnly (mod)) {
@@ -134,11 +192,12 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
134192 SILBuilderWithScope Builder (Inst, BuilderContext);
135193
136194 // If this is a conditional cast:
195+ //
137196 // We need a new fail BB in order to add a dealloc_stack to it
138- SILBasicBlock *ConvFailBB = nullptr ;
197+ SILBasicBlock *CastFailBB = nullptr ;
139198 if (isConditional) {
140199 auto CurrInsPoint = Builder.getInsertionPoint ();
141- ConvFailBB = splitBasicBlockAndBranch (Builder, &(*FailureBB->begin ()),
200+ CastFailBB = splitBasicBlockAndBranch (Builder, &(*FailureBB->begin ()),
142201 nullptr , nullptr );
143202 Builder.setInsertionPoint (CurrInsPoint);
144203 }
@@ -176,8 +235,8 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
176235 SILBasicBlock *castSuccessBB = F->createBasicBlock ();
177236 castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
178237 auto *ccbi = Builder.createCheckedCastBranch (
179- Loc, false , load, silBridgedTy, castSuccessBB, ConvFailBB );
180- splitEdge (ccbi, /* EdgeIdx to ConvFailBB */ 1 );
238+ Loc, false , load, silBridgedTy, castSuccessBB, CastFailBB );
239+ splitEdge (ccbi, /* EdgeIdx to CastFailBB */ 1 );
181240 Builder.setInsertionPoint (castSuccessBB);
182241 return {castSuccessBB->getArgument (0 ), ccbi};
183242 }
@@ -257,17 +316,17 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
257316 // Load from the optional.
258317 auto *SomeDecl = Builder.getASTContext ().getOptionalSomeDecl ();
259318
260- SILBasicBlock *ConvSuccessBB = Inst->getFunction ()->createBasicBlock ();
261- SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 1 > CaseBBs;
262- CaseBBs.push_back (
263- std::make_pair (mod. getASTContext (). getOptionalNoneDecl (), FailureBB));
264- Builder.createSwitchEnumAddr (Loc, InOutOptionalParam, ConvSuccessBB ,
319+ SILBasicBlock *BridgeSuccessBB = Inst->getFunction ()->createBasicBlock ();
320+ SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 2 > CaseBBs;
321+ CaseBBs.emplace_back (mod. getASTContext (). getOptionalNoneDecl (), FailureBB);
322+
323+ Builder.createSwitchEnumAddr (Loc, InOutOptionalParam, BridgeSuccessBB ,
265324 CaseBBs);
266325
267326 Builder.setInsertionPoint (FailureBB->begin ());
268327 Builder.createDeallocStack (Loc, Tmp);
269328
270- Builder.setInsertionPoint (ConvSuccessBB );
329+ Builder.setInsertionPoint (BridgeSuccessBB );
271330 auto Addr = Builder.createUncheckedTakeEnumDataAddr (Loc, InOutOptionalParam,
272331 SomeDecl);
273332
0 commit comments