@@ -618,13 +618,16 @@ class ReleaseBlockState : public BlockState {
618
618
}
619
619
620
620
// / constructor.
621
- ReleaseBlockState (bool IsExit, unsigned size, bool MultiIteration) {
621
+ // /
622
+ // / If \p InitOptimistic is true, the block in-bits are initialized to 1
623
+ // / which enables optimistic data flow evaluation.
624
+ ReleaseBlockState (bool InitOptimistic, unsigned size) {
622
625
// backward data flow.
623
626
// Initialize to true if we are running optimistic data flow, i.e.
624
627
// MultiIteration is true.
625
- BBSetIn.resize (size, MultiIteration );
628
+ BBSetIn.resize (size, InitOptimistic );
626
629
BBSetOut.resize (size, false );
627
- BBMaxSet.resize (size, !IsExit && MultiIteration );
630
+ BBMaxSet.resize (size, InitOptimistic );
628
631
629
632
// Genset and Killset are initially empty.
630
633
BBGenSet.resize (size, false );
@@ -735,6 +738,17 @@ bool ReleaseCodeMotionContext::requireIteration() {
735
738
}
736
739
737
740
void ReleaseCodeMotionContext::initializeCodeMotionDataFlow () {
741
+ // All blocks which are initialized with 1-bits. These are all blocks which
742
+ // eventually reach the function exit (return, throw), excluding the
743
+ // function exit blocks themselves.
744
+ // Optimistic initialization enables moving releases across loops. On the
745
+ // other hand, blocks, which never reach the function exit, e.g. infinite
746
+ // loop blocks, must be excluded. Otherwise we would end up inserting
747
+ // completely unrelated release instructions in such blocks.
748
+ llvm::SmallPtrSet<SILBasicBlock *, 32 > BlocksInitOptimistically;
749
+
750
+ llvm::SmallVector<SILBasicBlock *, 32 > Worklist;
751
+
738
752
// Find all the RC roots in the function.
739
753
for (auto &BB : *F) {
740
754
for (auto &II : BB) {
@@ -750,13 +764,25 @@ void ReleaseCodeMotionContext::initializeCodeMotionDataFlow() {
750
764
RCRootIndex[Root] = RCRootVault.size ();
751
765
RCRootVault.insert (Root);
752
766
}
767
+ if (MultiIteration && BB.getTerminator ()->isFunctionExiting ())
768
+ Worklist.push_back (&BB);
769
+ }
770
+
771
+ // Find all blocks from which there is a path to the function exit.
772
+ // Note: the Worklist is empty if we are not in MultiIteration mode.
773
+ while (!Worklist.empty ()) {
774
+ SILBasicBlock *BB = Worklist.pop_back_val ();
775
+ for (SILBasicBlock *Pred : BB->getPredecessorBlocks ()) {
776
+ if (BlocksInitOptimistically.insert (Pred).second )
777
+ Worklist.push_back (Pred);
778
+ }
753
779
}
754
780
755
781
// Initialize all the data flow bit vector for all basic blocks.
756
782
for (auto &BB : *F) {
757
783
BlockStates[&BB] = new (BPA.Allocate ())
758
- ReleaseBlockState (BB. getTerminator ()-> isFunctionExiting () ,
759
- RCRootVault.size (), MultiIteration );
784
+ ReleaseBlockState (BlocksInitOptimistically. count (&BB) != 0 ,
785
+ RCRootVault.size ());
760
786
}
761
787
}
762
788
@@ -1038,17 +1064,22 @@ class ARCCodeMotion : public SILFunctionTransform {
1038
1064
return ;
1039
1065
1040
1066
DEBUG (llvm::dbgs () << " *** ARCCM on function: " << F->getName () << " ***\n " );
1067
+
1068
+ PostOrderAnalysis *POA = PM->getAnalysis <PostOrderAnalysis>();
1069
+
1041
1070
// Split all critical edges.
1042
1071
//
1043
1072
// TODO: maybe we can do this lazily or maybe we should disallow SIL passes
1044
1073
// to create critical edges.
1045
1074
bool EdgeChanged = splitAllCriticalEdges (*F, false , nullptr , nullptr );
1075
+ if (EdgeChanged)
1076
+ POA->invalidateFunction (F);
1046
1077
1047
- llvm::SpecificBumpPtrAllocator<BlockState> BPA;
1048
- auto *PO = PM->getAnalysis <PostOrderAnalysis>()->get (F);
1078
+ auto *PO = POA->get (F);
1049
1079
auto *AA = PM->getAnalysis <AliasAnalysis>();
1050
1080
auto *RCFI = PM->getAnalysis <RCIdentityAnalysis>()->get (F);
1051
1081
1082
+ llvm::SpecificBumpPtrAllocator<BlockState> BPA;
1052
1083
bool InstChanged = false ;
1053
1084
if (Kind == Release) {
1054
1085
// TODO: we should consider Throw block as well, or better we should
0 commit comments