diff --git a/include/swift/SIL/DynamicCasts.h b/include/swift/SIL/DynamicCasts.h index 7b456154059..339130bd2e3 100644 --- a/include/swift/SIL/DynamicCasts.h +++ b/include/swift/SIL/DynamicCasts.h @@ -184,9 +184,12 @@ public: switch (getKind()) { case SILDynamicCastKind::CheckedCastAddrBranchInst: return cast(inst)->getConsumptionKind(); + // TODO: Bridged casts cannot be expressed by checked_cast_br or + // checked_cast_value_br yet. Should we ever support it, please + // review this code. case SILDynamicCastKind::CheckedCastBranchInst: case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return CastConsumptionKind::CopyOnSuccess; case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: return CastConsumptionKind::TakeAlways; case SILDynamicCastKind::UnconditionalCheckedCastInst: @@ -215,7 +218,7 @@ public: case SILDynamicCastKind::CheckedCastBranchInst: return cast(inst)->getSuccessBB(); case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return cast(inst)->getSuccessBB(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: case SILDynamicCastKind::UnconditionalCheckedCastInst: return nullptr; @@ -251,7 +254,7 @@ public: case SILDynamicCastKind::CheckedCastBranchInst: return cast(inst)->getFailureBB(); case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return cast(inst)->getFailureBB(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: case SILDynamicCastKind::UnconditionalCheckedCastInst: return nullptr; @@ -287,7 +290,7 @@ public: case SILDynamicCastKind::CheckedCastBranchInst: return cast(inst)->getOperand(); case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return cast(inst)->getOperand(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: return cast(inst)->getSrc(); case SILDynamicCastKind::UnconditionalCheckedCastInst: @@ -304,7 +307,8 @@ public: return cast(inst)->getDest(); case SILDynamicCastKind::CheckedCastBranchInst: case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + // TODO: Shouldn't this return getSuccessBlock()->getArgument(0)? + return SILValue(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: return cast(inst)->getDest(); case SILDynamicCastKind::UnconditionalCheckedCastInst: @@ -322,8 +326,9 @@ public: case SILDynamicCastKind::CheckedCastAddrBranchInst: return cast(inst)->getSourceType(); case SILDynamicCastKind::CheckedCastBranchInst: + return cast(inst)->getSourceType(); case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return cast(inst)->getSourceType(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: return cast(inst)->getSourceType(); case SILDynamicCastKind::UnconditionalCheckedCastInst: @@ -355,8 +360,9 @@ public: case SILDynamicCastKind::CheckedCastAddrBranchInst: return cast(inst)->getTargetType(); case SILDynamicCastKind::CheckedCastBranchInst: + return cast(inst)->getTargetType(); case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return cast(inst)->getTargetType(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: return cast(inst)->getTargetType(); case SILDynamicCastKind::UnconditionalCheckedCastInst: @@ -373,7 +379,7 @@ public: case SILDynamicCastKind::CheckedCastBranchInst: return cast(inst)->getCastType(); case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + return cast(inst)->getCastType(); case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: { auto *uccai = dyn_cast(inst); return uccai->getDest()->getType(); @@ -388,9 +394,8 @@ public: bool isSourceTypeExact() const { switch (getKind()) { - case SILDynamicCastKind::CheckedCastBranchInst: case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); + case SILDynamicCastKind::CheckedCastBranchInst: case SILDynamicCastKind::CheckedCastAddrBranchInst: case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: case SILDynamicCastKind::UnconditionalCheckedCastInst: @@ -421,13 +426,18 @@ public: bool isConditional() const { switch (getKind()) { - case SILDynamicCastKind::CheckedCastBranchInst: - case SILDynamicCastKind::CheckedCastValueBranchInst: - llvm_unreachable("unsupported"); case SILDynamicCastKind::CheckedCastAddrBranchInst: { auto f = classifyFeasibility(true /*allow wmo*/); return f == DynamicCastFeasibility::MaySucceed; } + case SILDynamicCastKind::CheckedCastBranchInst: { + auto f = classifyFeasibility(false /*allow wmo*/); + return f == DynamicCastFeasibility::MaySucceed; + } + case SILDynamicCastKind::CheckedCastValueBranchInst: { + auto f = classifyFeasibility(false /*allow wmo opts*/); + return f == DynamicCastFeasibility::MaySucceed; + } case SILDynamicCastKind::UnconditionalCheckedCastAddrInst: case SILDynamicCastKind::UnconditionalCheckedCastInst: return false; diff --git a/lib/SILOptimizer/Utils/CastOptimizer.cpp b/lib/SILOptimizer/Utils/CastOptimizer.cpp index c1ef2f16b2f..31831d4f002 100644 --- a/lib/SILOptimizer/Utils/CastOptimizer.cpp +++ b/lib/SILOptimizer/Utils/CastOptimizer.cpp @@ -795,21 +795,21 @@ SILInstruction *CastOptimizer::simplifyCheckedCastAddrBranchInst( SILInstruction * CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) { if (Inst->isExact()) { - auto *ARI = dyn_cast(stripUpCasts(Inst->getOperand())); + SILDynamicCastInst dynamicCast(Inst); + auto *ARI = dyn_cast(stripUpCasts(dynamicCast.getSource())); if (!ARI) return nullptr; // We know the dynamic type of the operand. SILBuilderWithScope Builder(Inst, BuilderContext); - auto Loc = Inst->getLoc(); - auto *SuccessBB = Inst->getSuccessBB(); - auto *FailureBB = Inst->getFailureBB(); + auto Loc = dynamicCast.getLocation(); - if (ARI->getType() == Inst->getCastType()) { + if (ARI->getType() == dynamicCast.getLoweredTargetType()) { // This exact cast will succeed. SmallVector Args; Args.push_back(ARI); - auto *NewI = Builder.createBranch(Loc, SuccessBB, Args); + auto *NewI = + Builder.createBranch(Loc, dynamicCast.getSuccessBlock(), Args); EraseInstAction(Inst); WillSucceedAction(); return NewI; @@ -819,8 +819,8 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) { // original casts value to the failure block. TinyPtrVector Args; if (Builder.hasOwnership()) - Args.push_back(Inst->getOperand()); - auto *NewI = Builder.createBranch(Loc, FailureBB, Args); + Args.push_back(dynamicCast.getSource()); + auto *NewI = Builder.createBranch(Loc, dynamicCast.getFailureBlock(), Args); EraseInstAction(Inst); WillFailAction(); return NewI; @@ -832,26 +832,23 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) { if (!Inst) return nullptr; - auto LoweredTargetType = Inst->getCastType(); - auto SourceType = Inst->getSourceType(); - auto TargetType = Inst->getTargetType(); - auto Loc = Inst->getLoc(); - auto *SuccessBB = Inst->getSuccessBB(); - auto *FailureBB = Inst->getFailureBB(); - auto Op = Inst->getOperand(); - auto &Mod = Inst->getModule(); - bool isSourceTypeExact = isa(Op); + SILDynamicCastInst dynamicCast(Inst); + auto LoweredTargetType = dynamicCast.getLoweredTargetType(); + auto Loc = dynamicCast.getLocation(); + auto *SuccessBB = dynamicCast.getSuccessBlock(); + auto Op = dynamicCast.getSource(); + auto &Mod = dynamicCast.getModule(); // Check if we can statically predict the outcome of the cast. - auto Feasibility = classifyDynamicCast(Mod.getSwiftModule(), SourceType, - TargetType, isSourceTypeExact); + auto Feasibility = + dynamicCast.classifyFeasibility(false /*allow whole module*/); SILBuilderWithScope Builder(Inst, BuilderContext); if (Feasibility == DynamicCastFeasibility::WillFail) { TinyPtrVector Args; if (Builder.hasOwnership()) Args.push_back(Inst->getOperand()); - auto *NewI = Builder.createBranch(Loc, FailureBB, Args); + auto *NewI = Builder.createBranch(Loc, dynamicCast.getFailureBlock(), Args); EraseInstAction(Inst); WillFailAction(); return NewI; @@ -860,15 +857,11 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) { bool ResultNotUsed = SuccessBB->getArgument(0)->use_empty(); SILValue CastedValue; if (Op->getType() != LoweredTargetType) { - auto Src = Inst->getOperand(); - auto Dest = SILValue(); // Apply the bridged cast optimizations. + // // TODO: Bridged casts cannot be expressed by checked_cast_br yet. // Should we ever support it, please review this code. - auto BridgedI = optimizeBridgedCasts( - Inst, CastConsumptionKind::CopyOnSuccess, - /* isConditional */ Feasibility == DynamicCastFeasibility::MaySucceed, - Src, Dest, SourceType, TargetType, nullptr, nullptr); + auto BridgedI = optimizeBridgedCasts(dynamicCast); if (BridgedI) { llvm_unreachable( @@ -886,12 +879,11 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) { // The unconditional_cast can be skipped, if the result of a cast // is not used afterwards. if (!ResultNotUsed) { - if (!canUseScalarCheckedCastInstructions(Mod, SourceType, TargetType)) + if (!dynamicCast.canUseScalarCheckedCastInstructions()) return nullptr; - CastedValue = emitSuccessfulScalarUnconditionalCast( - Builder, Mod.getSwiftModule(), Loc, Op, LoweredTargetType, - SourceType, TargetType, Inst); + CastedValue = + emitSuccessfulScalarUnconditionalCast(Builder, Loc, dynamicCast); } else { CastedValue = SILUndef::get(LoweredTargetType, Mod); } @@ -919,19 +911,16 @@ SILInstruction *CastOptimizer::simplifyCheckedCastValueBranchInst( if (!Inst) return nullptr; - auto LoweredTargetType = Inst->getCastType(); - auto SourceType = Inst->getSourceType(); - auto TargetType = Inst->getTargetType(); - auto Loc = Inst->getLoc(); - auto *SuccessBB = Inst->getSuccessBB(); - auto *FailureBB = Inst->getFailureBB(); - auto Op = Inst->getOperand(); - auto &Mod = Inst->getModule(); - bool isSourceTypeExact = isa(Op); + SILDynamicCastInst dynamicCast(Inst); + auto LoweredTargetType = dynamicCast.getLoweredTargetType(); + auto Loc = dynamicCast.getLocation(); + auto *SuccessBB = dynamicCast.getSuccessBlock(); + auto *FailureBB = dynamicCast.getFailureBlock(); + auto Op = dynamicCast.getSource(); + auto &Mod = dynamicCast.getModule(); // Check if we can statically predict the outcome of the cast. - auto Feasibility = classifyDynamicCast(Mod.getSwiftModule(), SourceType, - TargetType, isSourceTypeExact); + auto Feasibility = dynamicCast.classifyFeasibility(false /*allow wmo opts*/); SILBuilderWithScope Builder(Inst, BuilderContext); @@ -947,17 +936,11 @@ SILInstruction *CastOptimizer::simplifyCheckedCastValueBranchInst( bool ResultNotUsed = SuccessBB->getArgument(0)->use_empty(); SILValue CastedValue; if (Op->getType() != LoweredTargetType) { - auto Src = Inst->getOperand(); - auto Dest = SILValue(); // Apply the bridged cast optimizations. // TODO: Bridged casts cannot be expressed by checked_cast_value_br yet. // Once the support for opaque values has landed, please review this // code. - auto BridgedI = optimizeBridgedCasts( - Inst, CastConsumptionKind::CopyOnSuccess, - /* isConditional */ Feasibility == DynamicCastFeasibility::MaySucceed, - Src, Dest, SourceType, TargetType, nullptr, nullptr); - + auto *BridgedI = optimizeBridgedCasts(dynamicCast); if (BridgedI) { llvm_unreachable( "Bridged casts cannot be expressed by checked_cast_value_br yet"); @@ -974,13 +957,12 @@ SILInstruction *CastOptimizer::simplifyCheckedCastValueBranchInst( // The unconditional_cast can be skipped, if the result of a cast // is not used afterwards. - if (!canUseScalarCheckedCastInstructions(Mod, SourceType, TargetType)) + if (!dynamicCast.canUseScalarCheckedCastInstructions()) return nullptr; if (!ResultNotUsed) { - CastedValue = emitSuccessfulScalarUnconditionalCast( - Builder, Mod.getSwiftModule(), Loc, Op, LoweredTargetType, - SourceType, TargetType, Inst); + CastedValue = + emitSuccessfulScalarUnconditionalCast(Builder, Loc, dynamicCast); } else { CastedValue = SILUndef::get(LoweredTargetType, Mod); }