@@ -79,6 +79,63 @@ static SubstitutionMap lookupBridgeToObjCProtocolSubs(SILModule &mod,
79
79
// / _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
80
80
// / instance into a corresponding Swift type, conforming to
81
81
// / _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
+ // /
82
139
SILInstruction *
83
140
CastOptimizer::optimizeBridgedObjCToSwiftCast (SILDynamicCastInst dynamicCast) {
84
141
auto kind = dynamicCast.getKind ();
@@ -99,6 +156,7 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
99
156
}
100
157
101
158
SILValue src = dynamicCast.getSource ();
159
+
102
160
// Check if we have a source type that is address only. We do not support that
103
161
// today.
104
162
if (src->getType ().isAddressOnly (mod)) {
@@ -134,11 +192,12 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
134
192
SILBuilderWithScope Builder (Inst, BuilderContext);
135
193
136
194
// If this is a conditional cast:
195
+ //
137
196
// We need a new fail BB in order to add a dealloc_stack to it
138
- SILBasicBlock *ConvFailBB = nullptr ;
197
+ SILBasicBlock *CastFailBB = nullptr ;
139
198
if (isConditional) {
140
199
auto CurrInsPoint = Builder.getInsertionPoint ();
141
- ConvFailBB = splitBasicBlockAndBranch (Builder, &(*FailureBB->begin ()),
200
+ CastFailBB = splitBasicBlockAndBranch (Builder, &(*FailureBB->begin ()),
142
201
nullptr , nullptr );
143
202
Builder.setInsertionPoint (CurrInsPoint);
144
203
}
@@ -176,8 +235,8 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
176
235
SILBasicBlock *castSuccessBB = F->createBasicBlock ();
177
236
castSuccessBB->createPhiArgument (silBridgedTy, ValueOwnershipKind::Owned);
178
237
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 );
181
240
Builder.setInsertionPoint (castSuccessBB);
182
241
return {castSuccessBB->getArgument (0 ), ccbi};
183
242
}
@@ -257,17 +316,17 @@ CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
257
316
// Load from the optional.
258
317
auto *SomeDecl = Builder.getASTContext ().getOptionalSomeDecl ();
259
318
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 ,
265
324
CaseBBs);
266
325
267
326
Builder.setInsertionPoint (FailureBB->begin ());
268
327
Builder.createDeallocStack (Loc, Tmp);
269
328
270
- Builder.setInsertionPoint (ConvSuccessBB );
329
+ Builder.setInsertionPoint (BridgeSuccessBB );
271
330
auto Addr = Builder.createUncheckedTakeEnumDataAddr (Loc, InOutOptionalParam,
272
331
SomeDecl);
273
332
0 commit comments