Skip to content

[SIL] Add source formal type to checked_cast_br. #67583

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ private extension UnaryInstruction {
/// ```
/// %2 = upcast %1 : $Derived to $Base
/// %3 = init_existential_ref %2 : $Base : $Base, $AnyObject
/// checked_cast_br %3 : $AnyObject to Derived, bb1, bb2
/// checked_cast_br AnyObject in %3 : $AnyObject to Derived, bb1, bb2
/// ```
///
/// This makes it more likely that the cast can be constant folded because the source
/// operand's type is more accurate. In the example above, the cast reduces to
/// ```
/// checked_cast_br %1 : $Derived to Derived, bb1, bb2
/// checked_cast_br Derived in %1 : $Derived to Derived, bb1, bb2
/// ```
/// which can be trivially folded to always-succeeds.
///
Expand Down Expand Up @@ -97,13 +97,13 @@ private extension UnaryInstruction {
/// For example:
/// ```
/// %inst = upcast %sourceValue : $Derived to $Base
/// checked_cast_br %inst : $Base to Derived, success_block, failure_block
/// checked_cast_br Base in %inst : $Base to Derived, success_block, failure_block
/// ...
/// failure_block(%oldArg : $Base):
/// ```
/// is converted to:
/// ```
/// checked_cast_br %sourceValue : $Derived to Derived, success_block, failure_block
/// checked_cast_br Derived in %sourceValue : $Derived to Derived, success_block, failure_block
/// ...
/// failure_block(%newArg : $Derived):
/// %3 = upcast %newArg : $Derived to $Base
Expand Down
8 changes: 4 additions & 4 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2082,7 +2082,7 @@ derived from the ARC object. As an example, consider the following Swift/SIL::

// Consume '%1'. This means '%1' can no longer be used after this point. We
// rebind '%1' in the destination blocks (bbYes, bbNo).
checked_cast_br %1 : $Klass to $OtherKlass, bbYes, bbNo
checked_cast_br Klass in %1 : $Klass to $OtherKlass, bbYes, bbNo

bbYes(%2 : @owned $OtherKlass): // On success, the checked_cast_br forwards
// '%1' into '%2' after casting to OtherKlass.
Expand Down Expand Up @@ -8097,9 +8097,9 @@ checked_cast_br
sil-identifier ',' sil-identifier
sil-checked-cast-exact ::= '[' 'exact' ']'

checked_cast_br %0 : $A to $B, bb1, bb2
checked_cast_br %0 : $*A to $*B, bb1, bb2
checked_cast_br [exact] %0 : $A to $A, bb1, bb2
checked_cast_br A in %0 : $A to $B, bb1, bb2
checked_cast_br *A in %0 : $*A to $*B, bb1, bb2
checked_cast_br [exact] A in %0 : $A to $A, bb1, bb2
// $A and $B must be both object types or both address types
// bb1 must take a single argument of type $B or $*B
// bb2 must take no arguments
Expand Down
13 changes: 7 additions & 6 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2575,17 +2575,18 @@ class SILBuilder {
}

CheckedCastBranchInst *
createCheckedCastBranch(SILLocation Loc, bool isExact, SILValue op,
SILType destLoweredTy, CanType destFormalTy,
SILBasicBlock *successBB,
createCheckedCastBranch(SILLocation Loc, bool isExact, SILValue op,
CanType srcFormalTy, SILType destLoweredTy,
CanType destFormalTy, SILBasicBlock *successBB,
SILBasicBlock *failureBB,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter());

CheckedCastBranchInst *
createCheckedCastBranch(SILLocation Loc, bool isExact, SILValue op,
SILType destLoweredTy, CanType destFormalTy,
SILBasicBlock *successBB, SILBasicBlock *failureBB,
createCheckedCastBranch(SILLocation Loc, bool isExact, SILValue op,
CanType srcFormalTy, SILType destLoweredTy,
CanType destFormalTy, SILBasicBlock *successBB,
SILBasicBlock *failureBB,
ValueOwnershipKind forwardingOwnershipKind,
ProfileCounter Target1Count = ProfileCounter(),
ProfileCounter Target2Count = ProfileCounter());
Expand Down
1 change: 1 addition & 0 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -3128,6 +3128,7 @@ SILCloner<ImplClass>::visitCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
Inst, getBuilder().createCheckedCastBranch(
getOpLocation(Inst->getLoc()), Inst->isExact(),
getOpValue(Inst->getOperand()),
getOpASTType(Inst->getSourceFormalType()),
getOpType(Inst->getTargetLoweredType()),
getOpASTType(Inst->getTargetFormalType()), OpSuccBB, OpFailBB,
Inst->getForwardingOwnershipKind(), TrueCount, FalseCount));
Expand Down
13 changes: 7 additions & 6 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -10024,12 +10024,13 @@ class CheckedCastBranchInst final
CastBranchInstBase<OwnershipForwardingTermInst>> {
friend SILBuilder;

CanType SrcFormalTy;
SILType DestLoweredTy;
CanType DestFormalTy;
bool IsExact;

CheckedCastBranchInst(SILDebugLocation DebugLoc, bool IsExact,
SILValue Operand,
SILValue Operand, CanType SrcFormalTy,
ArrayRef<SILValue> TypeDependentOperands,
SILType DestLoweredTy, CanType DestFormalTy,
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB,
Expand All @@ -10041,21 +10042,21 @@ class CheckedCastBranchInst final
DebugLoc, Operand, TypeDependentOperands, SuccessBB, FailureBB,
Target1Count, Target2Count, forwardingOwnershipKind,
preservesOwnership),
DestLoweredTy(DestLoweredTy), DestFormalTy(DestFormalTy),
IsExact(IsExact) {}
SrcFormalTy(SrcFormalTy), DestLoweredTy(DestLoweredTy),
DestFormalTy(DestFormalTy), IsExact(IsExact) {}

static CheckedCastBranchInst *
create(SILDebugLocation DebugLoc, bool IsExact, SILValue Operand,
SILType DestLoweredTy, CanType DestFormalTy, SILBasicBlock *SuccessBB,
SILBasicBlock *FailureBB, SILFunction &F,
CanType SrcFormalTy, SILType DestLoweredTy, CanType DestFormalTy,
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB, SILFunction &F,
ProfileCounter Target1Count, ProfileCounter Target2Count,
ValueOwnershipKind forwardingOwnershipKind);

public:
bool isExact() const { return IsExact; }

SILType getSourceLoweredType() const { return getOperand()->getType(); }
CanType getSourceFormalType() const { return getSourceLoweredType().getASTType(); }
CanType getSourceFormalType() const { return SrcFormalTy; }

SILType getTargetLoweredType() const { return DestLoweredTy; }
CanType getTargetFormalType() const { return DestFormalTy; }
Expand Down
4 changes: 3 additions & 1 deletion lib/IRGen/GenCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ FailableCastResult irgen::emitClassIdenticalCast(IRGenFunction &IGF,
// of the metatype value to the subclass's static metatype instance.
//
// %1 = value_metatype $Super.Type, %0 : $A
// checked_cast_br [exact] %1 : $Super.Type to $Sub.Type
// checked_cast_br [exact] Super.Type in %1 : $Super.Type to $Sub.Type
// =>
// icmp eq %1, @metadata.Sub
llvm::Value *objectMetadata = isMetatype ? from :
Expand Down Expand Up @@ -883,6 +883,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,

bool sourceWrappedInOptional = false;

llvm::Optional<ConditionalDominanceScope> domScope;
if (auto sourceOptObjectType = sourceLoweredType.getOptionalObjectType()) {
// Translate the value from an enum representation to a possibly-null
// representation. Note that we assume that this projection is safe
Expand Down Expand Up @@ -912,6 +913,7 @@ void irgen::emitScalarCheckedCast(IRGenFunction &IGF,
Builder.CreateCondBr(isNotNil, isNotNilContBB, nilMergeBB);

Builder.emitBlock(isNotNilContBB);
domScope.emplace(IGF);
}
}

Expand Down
30 changes: 15 additions & 15 deletions lib/SIL/IR/SILBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ void SILBuilder::emitScopedBorrowOperation(SILLocation loc, SILValue original,
/// Example:
///
/// %mt = metatype $@thick C.Type
/// checked_cast_br %mt : $@thick C.Type to AnyObject.Type, bb1, bb2,
/// checked_cast_br C.Type in %mt : $@thick C.Type to AnyObject.Type, bb1, bb2,
/// forwarding: @owned
/// bb1(%arg : @owned AnyObject.Type):
///
Expand Down Expand Up @@ -717,30 +717,30 @@ SwitchEnumInst *SILBuilder::createSwitchEnum(
}

CheckedCastBranchInst *SILBuilder::createCheckedCastBranch(
SILLocation Loc, bool isExact, SILValue op,
SILType destLoweredTy, CanType destFormalTy,
SILBasicBlock *successBB, SILBasicBlock *failureBB,
ProfileCounter target1Count, ProfileCounter target2Count) {
SILLocation Loc, bool isExact, SILValue op, CanType srcFormalTy,
SILType destLoweredTy, CanType destFormalTy, SILBasicBlock *successBB,
SILBasicBlock *failureBB, ProfileCounter target1Count,
ProfileCounter target2Count) {
auto forwardingOwnership =
deriveForwardingOwnership(op, destLoweredTy, getFunction());
return createCheckedCastBranch(Loc, isExact, op, destLoweredTy, destFormalTy,
successBB, failureBB, forwardingOwnership,
target1Count, target2Count);
return createCheckedCastBranch(
Loc, isExact, op, srcFormalTy, destLoweredTy, destFormalTy, successBB,
failureBB, forwardingOwnership, target1Count, target2Count);
}

CheckedCastBranchInst *SILBuilder::createCheckedCastBranch(
SILLocation Loc, bool isExact, SILValue op, SILType destLoweredTy,
CanType destFormalTy, SILBasicBlock *successBB, SILBasicBlock *failureBB,
ValueOwnershipKind forwardingOwnershipKind, ProfileCounter target1Count,
ProfileCounter target2Count) {
SILLocation Loc, bool isExact, SILValue op, CanType srcFormalTy,
SILType destLoweredTy, CanType destFormalTy, SILBasicBlock *successBB,
SILBasicBlock *failureBB, ValueOwnershipKind forwardingOwnershipKind,
ProfileCounter target1Count, ProfileCounter target2Count) {
assert((!hasOwnership() || !failureBB->getNumArguments() ||
failureBB->getArgument(0)->getType() == op->getType()) &&
"failureBB's argument doesn't match incoming argument type");

return insertTerminator(CheckedCastBranchInst::create(
getSILDebugLocation(Loc), isExact, op, destLoweredTy, destFormalTy,
successBB, failureBB, getFunction(), target1Count, target2Count,
forwardingOwnershipKind));
getSILDebugLocation(Loc), isExact, op, srcFormalTy, destLoweredTy,
destFormalTy, successBB, failureBB, getFunction(), target1Count,
target2Count, forwardingOwnershipKind));
}

void SILBuilderWithScope::insertAfter(SILInstruction *inst,
Expand Down
12 changes: 6 additions & 6 deletions lib/SIL/IR/SILInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2551,8 +2551,8 @@ UnconditionalCheckedCastInst *UnconditionalCheckedCastInst::create(

CheckedCastBranchInst *CheckedCastBranchInst::create(
SILDebugLocation DebugLoc, bool IsExact, SILValue Operand,
SILType DestLoweredTy, CanType DestFormalTy, SILBasicBlock *SuccessBB,
SILBasicBlock *FailureBB, SILFunction &F,
CanType SrcFormalTy, SILType DestLoweredTy, CanType DestFormalTy,
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB, SILFunction &F,
ProfileCounter Target1Count, ProfileCounter Target2Count,
ValueOwnershipKind forwardingOwnershipKind) {
SILModule &module = F.getModule();
Expand All @@ -2561,12 +2561,12 @@ CheckedCastBranchInst *CheckedCastBranchInst::create(
SmallVector<SILValue, 8> TypeDependentOperands;
collectTypeDependentOperands(TypeDependentOperands, F, DestFormalTy);
unsigned size =
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
totalSizeToAlloc<swift::Operand>(3 + TypeDependentOperands.size());
void *Buffer = module.allocateInst(size, alignof(CheckedCastBranchInst));
return ::new (Buffer) CheckedCastBranchInst(
DebugLoc, IsExact, Operand, TypeDependentOperands, DestLoweredTy,
DestFormalTy, SuccessBB, FailureBB, Target1Count, Target2Count,
forwardingOwnershipKind, preservesOwnership);
DebugLoc, IsExact, Operand, SrcFormalTy, TypeDependentOperands,
DestLoweredTy, DestFormalTy, SuccessBB, FailureBB, Target1Count,
Target2Count, forwardingOwnershipKind, preservesOwnership);
}

MetatypeInst *MetatypeInst::create(SILDebugLocation Loc, SILType Ty,
Expand Down
1 change: 1 addition & 0 deletions lib/SIL/IR/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,7 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
void visitCheckedCastBranchInst(CheckedCastBranchInst *CI) {
if (CI->isExact())
*this << "[exact] ";
*this << CI->getSourceFormalType() << " in ";
*this << getIDAndType(CI->getOperand()) << " to " << CI->getTargetFormalType()
<< ", " << Ctx.getID(CI->getSuccessBB()) << ", "
<< Ctx.getID(CI->getFailureBB());
Expand Down
8 changes: 6 additions & 2 deletions lib/SIL/Parser/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4489,6 +4489,9 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
parseSILOptional(isExact, *this, "exact"))
return true;

if (parseASTType(SourceType) || parseVerbatim("in"))
return true;

if (parseTypedValueRef(Val, B) || parseVerbatim("to") ||
parseASTType(TargetType) || parseConditionalBranchDestinations())
return true;
Expand All @@ -4501,8 +4504,9 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,

auto opaque = Lowering::AbstractionPattern::getOpaque();
ResultVal = B.createCheckedCastBranch(
InstLoc, isExact, Val, F->getLoweredType(opaque, TargetType),
TargetType, getBBForReference(SuccessBBName, SuccessBBLoc),
InstLoc, isExact, Val, SourceType,
F->getLoweredType(opaque, TargetType), TargetType,
getBBForReference(SuccessBBName, SuccessBBLoc),
getBBForReference(FailureBBName, FailureBBLoc), forwardingOwnership);
break;
}
Expand Down
4 changes: 2 additions & 2 deletions lib/SIL/Utils/DynamicCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1417,8 +1417,8 @@ void swift::emitIndirectConditionalCastWithScalar(
})();

auto *ccb = B.createCheckedCastBranch(
loc, /*exact*/ false, srcValue, targetLoweredType, targetFormalType,
scalarSuccBB, scalarFailBB, TrueCount, FalseCount);
loc, /*exact*/ false, srcValue, sourceFormalType, targetLoweredType,
targetFormalType, scalarSuccBB, scalarFailBB, TrueCount, FalseCount);

// Emit the success block.
B.setInsertionPoint(scalarSuccBB); {
Expand Down
6 changes: 3 additions & 3 deletions lib/SILGen/SILGenBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,7 @@ ManagedValue SILGenBuilder::createUnconditionalCheckedCast(

void SILGenBuilder::createCheckedCastBranch(SILLocation loc, bool isExact,
ManagedValue op,
CanType sourceFormalTy,
SILType destLoweredTy,
CanType destFormalTy,
SILBasicBlock *trueBlock,
Expand All @@ -611,9 +612,8 @@ void SILGenBuilder::createCheckedCastBranch(SILLocation loc, bool isExact,
destFormalTy)) {
op = op.ensurePlusOne(SGF, loc);
}
createCheckedCastBranch(loc, isExact, op.forward(SGF),
destLoweredTy, destFormalTy,
trueBlock, falseBlock,
createCheckedCastBranch(loc, isExact, op.forward(SGF), sourceFormalTy,
destLoweredTy, destFormalTy, trueBlock, falseBlock,
Target1Count, Target2Count);
}

Expand Down
1 change: 1 addition & 0 deletions lib/SILGen/SILGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ class SILGenBuilder : public SILBuilder {
using SILBuilder::createCheckedCastBranch;
void createCheckedCastBranch(SILLocation loc, bool isExact,
ManagedValue op,
CanType sourceFormalTy,
SILType destLoweredTy,
CanType destFormalTy,
SILBasicBlock *trueBlock,
Expand Down
5 changes: 3 additions & 2 deletions lib/SILGen/SILGenDynamicCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,9 @@ namespace {
operandValue = operandValue.borrow(SGF, Loc);
}
SGF.B.createCheckedCastBranch(Loc, /*exact*/ false, operandValue,
origTargetTL.getLoweredType(), TargetType,
trueBB, falseBB, TrueCount, FalseCount);
SourceType, origTargetTL.getLoweredType(),
TargetType, trueBB, falseBB, TrueCount,
FalseCount);
}

// Emit the success block.
Expand Down
1 change: 1 addition & 0 deletions lib/SILOptimizer/Differentiation/VJPCloner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ class VJPCloner::Implementation final
// Create a new `checked_cast_branch` instruction.
getBuilder().createCheckedCastBranch(
ccbi->getLoc(), ccbi->isExact(), getOpValue(ccbi->getOperand()),
getOpASTType(ccbi->getSourceFormalType()),
getOpType(ccbi->getTargetLoweredType()),
getOpASTType(ccbi->getTargetFormalType()),
createTrampolineBasicBlock(ccbi, pbTupleVal, ccbi->getSuccessBB()),
Expand Down
2 changes: 1 addition & 1 deletion lib/SILOptimizer/Transforms/SILCodeMotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ enum OperandRelation {
///
/// bb1:
/// %3 = unchecked_enum_data %0 : $Optional<X>, #Optional.Some!enumelt
/// checked_cast_br [exact] %3 : $X to $X, bb4, bb5 // id: %4
/// checked_cast_br [exact] X in %3 : $X to $X, bb4, bb5 // id: %4
///
/// bb4(%10 : $X): // Preds: bb1
/// strong_release %10 : $X
Expand Down
3 changes: 2 additions & 1 deletion lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ static FullApplySite speculateMonomorphicTarget(FullApplySite AI,
// class instance is identical to the SILType.

CCBI = Builder.createCheckedCastBranch(AI.getLoc(), /*exact*/ true,
CMI->getOperand(),
CMI->getOperand(),
CMI->getOperand()->getType().getASTType(),
SILType::getPrimitiveObjectType(SubType),
SubType, Iden, Virt);
It = CCBI->getIterator();
Expand Down
11 changes: 9 additions & 2 deletions lib/SILOptimizer/Utils/CastOptimizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,9 @@ convertObjectToLoadableBridgeableType(SILBuilderWithScope &builder,

// Ok, we need to perform the full cast optimization. This means that we are
// going to replace the cast terminator in inst_block with a checked_cast_br.
auto *ccbi = builder.createCheckedCastBranch(loc, false, load, silBridgedTy,
auto *ccbi = builder.createCheckedCastBranch(loc, false, load,
dynamicCast.getBridgedSourceType(),
silBridgedTy,
dynamicCast.getBridgedTargetType(),
castSuccessBB, castFailBB);
splitEdge(ccbi, /* EdgeIdx to CastFailBB */ 1);
Expand Down Expand Up @@ -538,6 +540,7 @@ static SILValue computeFinalCastedValue(SILBuilderWithScope &builder,
auto loc = dynamicCast.getLocation();
auto convTy = newAI->getType();
bool isConditional = dynamicCast.isConditional();
auto sourceFormalTy = dynamicCast.getSourceFormalType();
auto destLoweredTy = dynamicCast.getTargetLoweredType().getObjectType();
auto destFormalTy = dynamicCast.getTargetFormalType();
assert(destLoweredTy == dynamicCast.getLoweredBridgedTargetObjectType() &&
Expand Down Expand Up @@ -581,7 +584,7 @@ static SILValue computeFinalCastedValue(SILBuilderWithScope &builder,
newAI->getFunction()->createBasicBlockAfter(newAI->getParent());
condBrSuccessBB->createPhiArgument(destLoweredTy, OwnershipKind::Owned);
builder.createCheckedCastBranch(loc, /* isExact*/ false, newAI,
destLoweredTy, destFormalTy,
sourceFormalTy, destLoweredTy, destFormalTy,
condBrSuccessBB, failureBB);
builder.setInsertionPoint(condBrSuccessBB, condBrSuccessBB->begin());
return condBrSuccessBB->getArgument(0);
Expand Down Expand Up @@ -1151,6 +1154,7 @@ SILInstruction *CastOptimizer::optimizeCheckedCastAddrBranchInst(
SILBuilderWithScope B(Inst, builderContext);
auto NewI = B.createCheckedCastBranch(
Loc, false /*isExact*/, MI,
Inst->getSourceFormalType(),
Inst->getTargetLoweredType().getObjectType(),
Inst->getTargetFormalType(),
SuccessBB, FailureBB, Inst->getTrueBBCount(),
Expand Down Expand Up @@ -1193,6 +1197,9 @@ CastOptimizer::optimizeCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
}
return B.createCheckedCastBranch(
dynamicCast.getLocation(), false /*isExact*/, mi,
// The cast is now from the the MetatypeInst, so get the source formal
// type from it.
mi->getType().getASTType(),
dynamicCast.getTargetLoweredType(),
dynamicCast.getTargetFormalType(),
dynamicCast.getSuccessBlock(),
Expand Down
Loading