Merge pull request #23699 from gottesmm/pr-eaf24f1b31fa093f1c5284bd0cd485d4567c1aba
diff --git a/lib/SILOptimizer/Utils/CastOptimizer.cpp b/lib/SILOptimizer/Utils/CastOptimizer.cpp
index 7990dc6..b3a4b74 100644
--- a/lib/SILOptimizer/Utils/CastOptimizer.cpp
+++ b/lib/SILOptimizer/Utils/CastOptimizer.cpp
@@ -79,6 +79,63 @@
/// _conditionallyBridgeFromObjectiveC_bridgeable which converts an ObjC
/// instance into a corresponding Swift type, conforming to
/// _ObjectiveCBridgeable.
+///
+/// Control Flow Modification Model
+/// ===============================
+///
+/// NOTE: In the following we assume that our src type is not address only. We
+/// do not support optimizing such source types today.
+///
+/// Unconditional Casts
+/// -------------------
+///
+/// In the case of unconditional casts, we do not touch the CFG at all. We
+/// perform the following optimizations:
+///
+/// 1. If the bridged type and the src type equal, we replace the cast with the
+/// apply.
+///
+/// 2. If src is an address and bridged type has the matching object type to
+/// src, just load the value and again replace the cast with the apply.
+///
+/// 3. If src is an address and after loading still doesn't match bridged type,
+/// insert an unconditional_checked_cast before calling the apply.
+///
+/// Conditional Casts
+/// -----------------
+///
+/// In the case of a conditional const (i.e. checked_cast_addr_br), we transform
+/// the following CFG:
+///
+/// ```
+/// InstBlock (checked_cast_addr_br) -> FailureBB -> FailureSucc
+/// \
+/// \----------------------------> SuccessBB -> SuccessSucc
+/// ```
+///
+/// to a CFG of the following form:
+///
+/// ```
+/// InstBlock (checked_cast_br) -> CastFailBB -> FailureBB -> FailureSucc
+/// | ^
+/// \-> CastSuccessBB (bridge call + switch) --|
+/// |
+/// \-> BridgeSuccessBB -> SuccessBB -> SuccessSucc
+/// ```
+///
+/// NOTE: That if the underlying src type matches the type of the underlying
+/// bridge source object, we can omit the initial checked_cast_br and just load
+/// the value + branch to the CastSuccessBB. This results instead in the
+/// following CFG:
+///
+/// ```
+/// InstBlock (br) FailureBB -> FailureSucc
+/// | ^
+/// \-> CastSuccessBB (bridge call + switch) --|
+/// |
+/// \-> BridgeSuccessBB -> SuccessBB -> SuccessSucc
+/// ```
+///
SILInstruction *
CastOptimizer::optimizeBridgedObjCToSwiftCast(SILDynamicCastInst dynamicCast) {
auto kind = dynamicCast.getKind();
@@ -99,6 +156,7 @@
}
SILValue src = dynamicCast.getSource();
+
// Check if we have a source type that is address only. We do not support that
// today.
if (src->getType().isAddressOnly(mod)) {
@@ -134,11 +192,12 @@
SILBuilderWithScope Builder(Inst, BuilderContext);
// If this is a conditional cast:
+ //
// We need a new fail BB in order to add a dealloc_stack to it
- SILBasicBlock *ConvFailBB = nullptr;
+ SILBasicBlock *CastFailBB = nullptr;
if (isConditional) {
auto CurrInsPoint = Builder.getInsertionPoint();
- ConvFailBB = splitBasicBlockAndBranch(Builder, &(*FailureBB->begin()),
+ CastFailBB = splitBasicBlockAndBranch(Builder, &(*FailureBB->begin()),
nullptr, nullptr);
Builder.setInsertionPoint(CurrInsPoint);
}
@@ -176,8 +235,8 @@
SILBasicBlock *castSuccessBB = F->createBasicBlock();
castSuccessBB->createPhiArgument(silBridgedTy, ValueOwnershipKind::Owned);
auto *ccbi = Builder.createCheckedCastBranch(
- Loc, false, load, silBridgedTy, castSuccessBB, ConvFailBB);
- splitEdge(ccbi, /* EdgeIdx to ConvFailBB */ 1);
+ Loc, false, load, silBridgedTy, castSuccessBB, CastFailBB);
+ splitEdge(ccbi, /* EdgeIdx to CastFailBB */ 1);
Builder.setInsertionPoint(castSuccessBB);
return {castSuccessBB->getArgument(0), ccbi};
}
@@ -257,17 +316,17 @@
// Load from the optional.
auto *SomeDecl = Builder.getASTContext().getOptionalSomeDecl();
- SILBasicBlock *ConvSuccessBB = Inst->getFunction()->createBasicBlock();
- SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 1> CaseBBs;
- CaseBBs.push_back(
- std::make_pair(mod.getASTContext().getOptionalNoneDecl(), FailureBB));
- Builder.createSwitchEnumAddr(Loc, InOutOptionalParam, ConvSuccessBB,
+ SILBasicBlock *BridgeSuccessBB = Inst->getFunction()->createBasicBlock();
+ SmallVector<std::pair<EnumElementDecl *, SILBasicBlock *>, 2> CaseBBs;
+ CaseBBs.emplace_back(mod.getASTContext().getOptionalNoneDecl(), FailureBB);
+
+ Builder.createSwitchEnumAddr(Loc, InOutOptionalParam, BridgeSuccessBB,
CaseBBs);
Builder.setInsertionPoint(FailureBB->begin());
Builder.createDeallocStack(Loc, Tmp);
- Builder.setInsertionPoint(ConvSuccessBB);
+ Builder.setInsertionPoint(BridgeSuccessBB);
auto Addr = Builder.createUncheckedTakeEnumDataAddr(Loc, InOutOptionalParam,
SomeDecl);