@@ -621,9 +621,10 @@ findMatchingRetainsInner(SILBasicBlock *BB, SILValue V) {
621
621
return std::make_pair (FindRetainKind::None, nullptr );
622
622
}
623
623
624
- ConsumedArgToEpilogueReleaseMatcher::ConsumedArgToEpilogueReleaseMatcher (
625
- RCIdentityFunctionInfo *RCFI, SILFunction *F, ExitKind Kind)
626
- : F(F), RCFI(RCFI), Kind(Kind) {
624
+ ConsumedArgToEpilogueReleaseMatcher::
625
+ ConsumedArgToEpilogueReleaseMatcher (RCIdentityFunctionInfo *RCFI,
626
+ SILFunction *F, ExitKind Kind)
627
+ : F(F), RCFI(RCFI), Kind(Kind) {
627
628
recompute ();
628
629
}
629
630
@@ -674,26 +675,52 @@ isRedundantRelease(ReleaseList Insts, SILValue Base, SILValue Derived) {
674
675
675
676
bool
676
677
ConsumedArgToEpilogueReleaseMatcher::
677
- releaseAllNonTrivials (ReleaseList Insts, SILValue Base ) {
678
+ releaseArgument (ReleaseList Insts, SILValue Arg ) {
678
679
// Reason about whether all parts are released.
679
680
SILModule *Mod = &(*Insts.begin ())->getModule ();
680
681
681
682
// These are the list of SILValues that are actually released.
682
683
ProjectionPathSet Paths;
683
684
for (auto &I : Insts) {
684
- auto PP = ProjectionPath::getProjectionPath (Base , I->getOperand (0 ));
685
+ auto PP = ProjectionPath::getProjectionPath (Arg , I->getOperand (0 ));
685
686
if (!PP)
686
687
return false ;
687
688
Paths.insert (PP.getValue ());
688
689
}
689
690
690
691
// Is there an uncovered non-trivial type.
691
- return !ProjectionPath::hasUncoveredNonTrivials (Base ->getType (), Mod, Paths);
692
+ return !ProjectionPath::hasUncoveredNonTrivials (Arg ->getType (), Mod, Paths);
692
693
}
693
694
694
695
void
695
696
ConsumedArgToEpilogueReleaseMatcher::
696
- findMatchingReleases (SILBasicBlock *BB) {
697
+ processMatchingReleases () {
698
+ // If we can not find a releases for all parts with reference semantics
699
+ // that means we did not find all releases for the base.
700
+ for (auto Arg : ArgInstMap) {
701
+ // If an argument has a single release and it is rc-identical to the
702
+ // SILArgument. Then we do not need to use projection to check for whether
703
+ // all non-trivial fields are covered.
704
+ if (Arg.second .size () == 1 ) {
705
+ SILInstruction *I = *Arg.second .begin ();
706
+ SILValue RV = I->getOperand (0 );
707
+ if (Arg.first == RCFI->getRCIdentityRoot (RV))
708
+ continue ;
709
+ }
710
+
711
+ // OK. we have multiple epilogue releases for this argument, check whether
712
+ // it has covered all fields with reference semantic in the argument.
713
+ if (releaseArgument (Arg.second , Arg.first ))
714
+ continue ;
715
+
716
+ // Clear any releases found for this argument.
717
+ ArgInstMap.erase (Arg.first );
718
+ }
719
+ }
720
+
721
+ void
722
+ ConsumedArgToEpilogueReleaseMatcher::
723
+ collectMatchingReleases (SILBasicBlock *BB) {
697
724
// Iterate over the instructions post-order and find final releases
698
725
// associated with each arguments.
699
726
//
@@ -734,7 +761,7 @@ findMatchingReleases(SILBasicBlock *BB) {
734
761
auto *Arg = dyn_cast<SILArgument>(Op);
735
762
// If this is not a SILArgument, maybe it is a part of a SILArgument.
736
763
// This is possible after we expand release instructions in SILLowerAgg pass.
737
- if (!Arg) {
764
+ if (!Arg) {
738
765
Arg = dyn_cast<SILArgument>(stripValueProjections (OrigOp));
739
766
}
740
767
@@ -769,29 +796,16 @@ findMatchingReleases(SILBasicBlock *BB) {
769
796
// Record it.
770
797
Iter->second .push_back (Target);
771
798
}
799
+ }
772
800
773
- // If we can not find a releases for all parts with reference semantics
774
- // that means we did not find all releases for the base.
775
- llvm::DenseSet<SILArgument *> ArgToRemove;
776
- for (auto &Arg : ArgInstMap) {
777
- // If an argument has a single release and it is rc-identical to the
778
- // SILArgument. Then we do not need to use projection to check for whether
779
- // all non-trivial fields are covered. This is a short-cut to avoid
780
- // projection for cost as well as accuracy. Projection currently does not
781
- // support single incoming argument as rc-identity does whereas rc-identity
782
- // does.
783
- if (Arg.second .size () == 1 ) {
784
- SILInstruction *I = *Arg.second .begin ();
785
- SILValue RV = I->getOperand (0 );
786
- if (Arg.first == RCFI->getRCIdentityRoot (RV))
787
- continue ;
788
- }
789
- if (!releaseAllNonTrivials (Arg.second , Arg.first ))
790
- ArgToRemove.insert (Arg.first );
791
- }
792
-
793
- for (auto &X : ArgToRemove)
794
- ArgInstMap.erase (ArgInstMap.find (X));
801
+ void
802
+ ConsumedArgToEpilogueReleaseMatcher::
803
+ findMatchingReleases (SILBasicBlock *BB) {
804
+ // Walk the given basic block to find all the epilogue releases.
805
+ collectMatchingReleases (BB);
806
+ // We've exited the epilogue sequence, try to find out which parameter we
807
+ // have all the epilogue releases for and which one we did not.
808
+ processMatchingReleases ();
795
809
}
796
810
797
811
// ===----------------------------------------------------------------------===//
0 commit comments