@@ -916,16 +916,57 @@ static bool couldRemoveRelease(SILBasicBlock *SrcBB, SILValue SrcV,
916
916
return IsReleaseOfDest;
917
917
}
918
918
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
+
919
952
// / tryJumpThreading - Check to see if it looks profitable to duplicate the
920
953
// / destination of an unconditional jump into the bottom of this block.
921
954
bool SimplifyCFG::tryJumpThreading (BranchInst *BI) {
922
955
auto *DestBB = BI->getDestBB ();
923
956
auto *SrcBB = BI->getParent ();
957
+ TermInst *destTerminator = DestBB->getTerminator ();
924
958
// If the destination block ends with a return, we don't want to duplicate it.
925
959
// We want to maintain the canonical form of a single return where possible.
926
- if (DestBB-> getTerminator () ->isFunctionExiting ())
960
+ if (destTerminator ->isFunctionExiting ())
927
961
return false ;
928
962
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
+
929
970
// We don't have a great cost model at the SIL level, so we don't want to
930
971
// blissly duplicate tons of code with a goal of improved performance (we'll
931
972
// leave that to LLVM). However, doing limited code duplication can lead to
@@ -956,11 +997,29 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
956
997
}
957
998
}
958
999
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)) {
962
1022
ThreadingBudget = 4 ;
963
- break ;
964
1023
}
965
1024
}
966
1025
}
@@ -976,7 +1035,7 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) {
976
1035
// control flow. Still, we make an exception for switch_enum.
977
1036
bool DestIsLoopHeader = (LoopHeaders.count (DestBB) != 0 );
978
1037
if (DestIsLoopHeader) {
979
- if (!isa<SwitchEnumInst>(DestBB-> getTerminator () ))
1038
+ if (!isa<SwitchEnumInst>(destTerminator ))
980
1039
return false ;
981
1040
}
982
1041
@@ -1286,8 +1345,7 @@ bool SimplifyCFG::simplifyBranchBlock(BranchInst *BI) {
1286
1345
// If this unconditional branch has BBArgs, check to see if duplicating the
1287
1346
// destination would allow it to be simplified. This is a simple form of jump
1288
1347
// threading.
1289
- if (!isVeryLargeFunction && !BI->getArgs ().empty () &&
1290
- tryJumpThreading (BI))
1348
+ if (!isVeryLargeFunction && tryJumpThreading (BI))
1291
1349
return true ;
1292
1350
1293
1351
return Simplified;
0 commit comments