Skip to content

Commit f40e9ef

Browse files
committed
Rewrite switch dispatch emission.
Specialization now recurses on only that prefix of the current matrix which shares a specialization form (essentially, a pattern kind) with the head row. This is inferior to the previous algorithm in a number of ways: we may require more switches to perform a single dispatch, and we may introduce more redundant variables in the leaves. However, it also means that we will have fully specialized a row along exactly one path in the decision tree, which makes it much easier to work with dispatches that introduce new cleanups. This change also changes switch-dispatch to use the new dynamic-cast instructions. Incidentally fixes rdar://16401831. Swift SVN r19336
1 parent ba597ec commit f40e9ef

8 files changed

+2015
-1940
lines changed

lib/SILGen/SILGenExpr.cpp

+49-35
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,7 @@ namespace {
15951595
SILBasicBlock *trueBB = SGF.B.splitBlockForFallthrough();
15961596

15971597
// Emit the branch.
1598+
SILValue scalarOperandValue;
15981599
SILValue resultBuffer;
15991600
if (Strategy == CastStrategy::Address) {
16001601
assert(operand.getType().isAddress());
@@ -1605,9 +1606,13 @@ namespace {
16051606
resultBuffer, TargetType,
16061607
trueBB, falseBB);
16071608
} else {
1608-
assert(!operand.getType().isAddress());
1609-
SGF.B.createCheckedCastBranch(Loc, /*exact*/ false,
1610-
operand.forward(SGF),
1609+
// Tolerate being passed an address here. It comes up during switch
1610+
//emission.
1611+
scalarOperandValue = operand.forward(SGF);
1612+
if (scalarOperandValue.getType().isAddress()) {
1613+
scalarOperandValue = SGF.B.createLoad(Loc, scalarOperandValue);
1614+
}
1615+
SGF.B.createCheckedCastBranch(Loc, /*exact*/ false, scalarOperandValue,
16111616
origTargetTL.getLoweredType(),
16121617
trueBB, falseBB);
16131618
}
@@ -1628,6 +1633,7 @@ namespace {
16281633
}
16291634

16301635
handleTrue(result);
1636+
assert(!SGF.B.hasValidInsertionPoint() && "handler did not end block");
16311637
}
16321638

16331639
// Emit the failure block.
@@ -1637,10 +1643,11 @@ namespace {
16371643
// If we're using the scalar strategy, handle the consumption rules.
16381644
if (Strategy != CastStrategy::Address &&
16391645
shouldDestroyOnFailure(consumption)) {
1640-
SGF.B.emitReleaseValueOperation(Loc, operand.getValue());
1646+
SGF.B.emitReleaseValueOperation(Loc, scalarOperandValue);
16411647
}
16421648

16431649
handleFalse();
1650+
assert(!SGF.B.hasValidInsertionPoint() && "handler did not end block");
16441651
}
16451652
}
16461653

@@ -1742,38 +1749,33 @@ static RValue emitUnconditionalCheckedCast(SILGenFunction &SGF,
17421749
return emitter.emitUnconditionalCast(operandValue, C);
17431750
}
17441751

1745-
SILValue
1746-
SILGenFunction::emitCheckedCastAbstractionChange(SILLocation loc,
1747-
SILValue original,
1748-
const TypeLowering &origTL,
1749-
ArrayRef<const TypeLowering *> castTLs) {
1750-
// If we're casting a thin metatype, make it thick.
1751-
if (auto metatype = original.getType().getAs<MetatypeType>()) {
1752-
if (metatype->getRepresentation() == MetatypeRepresentation::Thin) {
1753-
auto thickTy = CanMetatypeType::get(metatype.getInstanceType(),
1754-
MetatypeRepresentation::Thick);
1755-
return B.createMetatype(loc, SILType::getPrimitiveObjectType(thickTy));
1756-
}
1757-
return original;
1758-
}
1759-
1760-
// If the original type is already address-only, we don't need to abstract
1761-
// further.
1762-
if (origTL.isAddressOnly()) {
1763-
return SILValue();
1764-
}
1765-
1766-
// If any of the cast-to types are address-only, spill to a temporary.
1767-
if (std::find_if(castTLs.begin(), castTLs.end(),
1768-
[](const TypeLowering *tl){ return tl->isAddressOnly(); })
1769-
!= castTLs.end()) {
1770-
SILValue temp = emitTemporaryAllocation(loc, origTL.getLoweredType());
1771-
B.createStore(loc, original, temp);
1772-
return temp;
1752+
/// Treating this as a successful operation, turn a CMV into a +1 MV.
1753+
ManagedValue SILGenFunction::getManagedValue(SILLocation loc,
1754+
ConsumableManagedValue value) {
1755+
// If the consumption rules say that this is already +1 given a
1756+
// successful operation, just use the value.
1757+
if (value.isOwned())
1758+
return value.getFinalManagedValue();
1759+
1760+
SILType valueTy = value.getType();
1761+
auto &valueTL = getTypeLowering(valueTy);
1762+
1763+
// If the type is trivial, it's always +1.
1764+
if (valueTL.isTrivial())
1765+
return ManagedValue::forUnmanaged(value.getValue());
1766+
1767+
// If it's an object, retain and enter a release cleanup.
1768+
if (valueTy.isObject()) {
1769+
valueTL.emitRetainValue(B, loc, value.getValue());
1770+
return emitManagedRValueWithCleanup(value.getValue(), valueTL);
17731771
}
1774-
1775-
// Otherwise, no abstraction change is needed.
1776-
return SILValue();
1772+
1773+
// Otherwise, produce a temporary and copy into that.
1774+
auto temporary = emitTemporary(loc, valueTL);
1775+
valueTL.emitCopyInto(B, loc, value.getValue(), temporary->getAddress(),
1776+
IsNotTake, IsInitialization);
1777+
temporary->finishInitialization(*this);
1778+
return temporary->getManagedAddress();
17771779
}
17781780

17791781
void SILGenFunction::emitCheckedCastBranch(SILLocation loc, Expr *source,
@@ -1787,6 +1789,18 @@ void SILGenFunction::emitCheckedCastBranch(SILLocation loc, Expr *source,
17871789
handleTrue, handleFalse);
17881790
}
17891791

1792+
void SILGenFunction::emitCheckedCastBranch(SILLocation loc,
1793+
ConsumableManagedValue src,
1794+
CanType sourceType,
1795+
CanType targetType,
1796+
SGFContext ctx,
1797+
std::function<void(ManagedValue)> handleTrue,
1798+
std::function<void()> handleFalse) {
1799+
CheckedCastEmitter emitter(*this, loc, sourceType, targetType);
1800+
emitter.emitConditional(src.getFinalManagedValue(), src.getFinalConsumption(),
1801+
ctx, handleTrue, handleFalse);
1802+
}
1803+
17901804
std::pair<SILBasicBlock*, SILBasicBlock*>
17911805
SILGenFunction::emitCheckedCastBranch(SILLocation loc,
17921806
SILValue original,

lib/SILGen/SILGenFunction.h

+10-16
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,10 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
743743

744744
void emitReturnExpr(SILLocation loc, Expr *ret);
745745

746+
/// Turn a consumable managed value into a +1 managed value.
747+
ManagedValue getManagedValue(SILLocation loc,
748+
ConsumableManagedValue value);
749+
746750
/// Convert a value with the abstraction patterns of the original type
747751
/// to a value with the abstraction patterns of the substituted type.
748752
ManagedValue emitOrigToSubstValue(SILLocation loc, ManagedValue input,
@@ -828,22 +832,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
828832
/// Emit a dynamic subscript.
829833
RValue emitDynamicSubscriptExpr(DynamicSubscriptExpr *e, SGFContext c);
830834

831-
/// \brief Emits the abstraction change needed, if any, to perform casts from
832-
/// the type represented by \c origTL to each of the types represented by
833-
/// \c castTLs.
834-
///
835-
/// \param loc The AST location associated with the operation.
836-
/// \param original The value to cast.
837-
/// \param origTL The original type.
838-
/// \param castTLs The types to which to cast.
839-
///
840-
/// \returns The value shifted to the highest abstraction level necessary
841-
/// for the casts, or a null SILValue if no abstraction changes are needed.
842-
SILValue emitCheckedCastAbstractionChange(SILLocation loc,
843-
SILValue original,
844-
const TypeLowering &origTL,
845-
ArrayRef<const TypeLowering *> castTLs);
846-
847835
/// \brief Emit a conditional checked cast branch. Does not re-abstract the
848836
/// argument to the success branch. Terminates the current BB.
849837
///
@@ -867,6 +855,12 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
867855
const TypeLowering &castTL,
868856
CheckedCastKind kind);
869857

858+
void emitCheckedCastBranch(SILLocation loc, ConsumableManagedValue src,
859+
CanType sourceType, CanType targetType,
860+
SGFContext C,
861+
std::function<void(ManagedValue)> handleTrue,
862+
std::function<void()> handleFalse);
863+
870864
void emitCheckedCastBranch(SILLocation loc, Expr *src,
871865
Type targetType, SGFContext C,
872866
std::function<void(ManagedValue)> handleTrue,

0 commit comments

Comments
 (0)