Skip to content

Commit 4e7d1c1

Browse files
authored
Merge pull request #23699 from gottesmm/pr-eaf24f1b31fa093f1c5284bd0cd485d4567c1aba
2 parents 2c02cff + 57b923b commit 4e7d1c1

File tree

1 file changed

+69
-10
lines changed

1 file changed

+69
-10
lines changed

lib/SILOptimizer/Utils/CastOptimizer.cpp

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
///
82139
SILInstruction *
83140
CastOptimizer::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

Comments
 (0)