@@ -916,16 +916,57 @@ static bool couldRemoveRelease(SILBasicBlock *SrcBB, SILValue SrcV,
916916 return IsReleaseOfDest;
917917}
918918
919+ // / Returns true if any instruction in \p block may write memory.
920+ static bool blockMayWriteMemory (SILBasicBlock *block) {
921+ for (auto instAndIdx : llvm::enumerate (*block)) {
922+ if (instAndIdx.value ().mayWriteToMemory ())
923+ return true ;
924+ // Only look at the first 20 instructions to avoid compile time problems for
925+ // corner cases of very large blocks without memory writes.
926+ // 20 instructions is more than enough.
927+ if (instAndIdx.index () > 50 )
928+ return true ;
929+ }
930+ return false ;
931+ }
932+
933+ // Returns true if \p block contains an injected an enum case into \p enumAddr
934+ // which is valid at the end of the block.
935+ static bool hasInjectedEnumAtEndOfBlock (SILBasicBlock *block, SILValue enumAddr) {
936+ for (auto instAndIdx : llvm::enumerate (llvm::reverse (*block))) {
937+ SILInstruction &inst = instAndIdx.value ();
938+ if (auto *injectInst = dyn_cast<InjectEnumAddrInst>(&inst)) {
939+ return injectInst->getOperand () == enumAddr;
940+ }
941+ if (inst.mayWriteToMemory ())
942+ return false ;
943+ // Only look at the first 20 instructions to avoid compile time problems for
944+ // corner cases of very large blocks without memory writes.
945+ // 20 instructions is more than enough.
946+ if (instAndIdx.index () > 50 )
947+ return false ;
948+ }
949+ return false ;
950+ }
951+
919952// / tryJumpThreading - Check to see if it looks profitable to duplicate the
920953// / destination of an unconditional jump into the bottom of this block.
921954bool SimplifyCFG::tryJumpThreading (BranchInst *BI) {
922955 auto *DestBB = BI->getDestBB ();
923956 auto *SrcBB = BI->getParent ();
957+ TermInst *destTerminator = DestBB->getTerminator ();
924958 // If the destination block ends with a return, we don't want to duplicate it.
925959 // We want to maintain the canonical form of a single return where possible.
926- if (DestBB-> getTerminator () ->isFunctionExiting ())
960+ if (destTerminator ->isFunctionExiting ())
927961 return false ;
928962
963+ // Jump threading only makes sense if there is an argument on the branch
964+ // (which is reacted on in the DestBB), or if this goes through a memory
965+ // location (switch_enum_addr is the only adress-instruction which we
966+ // currently handle).
967+ if (BI->getArgs ().empty () && !isa<SwitchEnumAddrInst>(destTerminator))
968+ return false ;
969+
929970 // We don't have a great cost model at the SIL level, so we don't want to
930971 // blissly duplicate tons of code with a goal of improved performance (we'll
931972 // leave that to LLVM). However, doing limited code duplication can lead to
@@ -956,11 +997,29 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
956997 }
957998 }
958999
959- if (ThreadingBudget == 0 && isa<CondBranchInst>(DestBB->getTerminator ())) {
960- for (auto V : BI->getArgs ()) {
961- if (isa<IntegerLiteralInst>(V) || isa<FloatLiteralInst>(V)) {
1000+ if (ThreadingBudget == 0 ) {
1001+ if (isa<CondBranchInst>(destTerminator)) {
1002+ for (auto V : BI->getArgs ()) {
1003+ if (isa<IntegerLiteralInst>(V) || isa<FloatLiteralInst>(V)) {
1004+ ThreadingBudget = 4 ;
1005+ break ;
1006+ }
1007+ }
1008+ } else if (auto *SEA = dyn_cast<SwitchEnumAddrInst>(destTerminator)) {
1009+ // If the branch-block injects a certain enum case and the destination
1010+ // switches on that enum, it's worth jump threading. E.g.
1011+ //
1012+ // inject_enum_addr %enum : $*Optional<T>, #Optional.some
1013+ // ... // no memory writes here
1014+ // br DestBB
1015+ // DestBB:
1016+ // ... // no memory writes here
1017+ // switch_enum_addr %enum : $*Optional<T>, case #Optional.some ...
1018+ //
1019+ SILValue enumAddr = SEA->getOperand ();
1020+ if (!blockMayWriteMemory (DestBB) &&
1021+ hasInjectedEnumAtEndOfBlock (SrcBB, enumAddr)) {
9621022 ThreadingBudget = 4 ;
963- break ;
9641023 }
9651024 }
9661025 }
@@ -976,7 +1035,7 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
9761035 // control flow. Still, we make an exception for switch_enum.
9771036 bool DestIsLoopHeader = (LoopHeaders.count (DestBB) != 0 );
9781037 if (DestIsLoopHeader) {
979- if (!isa<SwitchEnumInst>(DestBB-> getTerminator () ))
1038+ if (!isa<SwitchEnumInst>(destTerminator ))
9801039 return false ;
9811040 }
9821041
@@ -1286,8 +1345,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
12861345 // If this unconditional branch has BBArgs, check to see if duplicating the
12871346 // destination would allow it to be simplified. This is a simple form of jump
12881347 // threading.
1289- if (!isVeryLargeFunction && !BI->getArgs ().empty () &&
1290- tryJumpThreading (BI))
1348+ if (!isVeryLargeFunction && tryJumpThreading (BI))
12911349 return true ;
12921350
12931351 return Simplified;
0 commit comments