Skip to content

Commit b2b5247

Browse files
committed
Merge pull request #1756 from trentxintong/FSO
Minor refactoring in epilogue release matcher
2 parents 67703b9 + a191ae7 commit b2b5247

File tree

2 files changed

+62
-33
lines changed

2 files changed

+62
-33
lines changed

include/swift/SILOptimizer/Analysis/ARCAnalysis.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,17 @@ class ConsumedArgToEpilogueReleaseMatcher {
197197
bool isRedundantRelease(ReleaseList Insts, SILValue Base, SILValue Derived);
198198

199199
/// Return true if we have a release instruction for all the reference
200-
/// semantics part of \p Base.
201-
bool releaseAllNonTrivials(ReleaseList Insts, SILValue Base);
200+
/// semantics part of \p Argument.
201+
bool releaseArgument(ReleaseList Insts, SILValue Argument);
202+
203+
/// Walk the basic block and find all the releases that match to function
204+
/// arguments.
205+
void collectMatchingReleases(SILBasicBlock *BB);
206+
207+
/// For every argument in the function, check to see whether all epilogue
208+
/// releases are found. Clear all releases for the argument if not all
209+
/// epilogue releases are found.
210+
void processMatchingReleases();
202211

203212
public:
204213
/// Finds matching releases in the return block of the function \p F.
@@ -211,11 +220,17 @@ class ConsumedArgToEpilogueReleaseMatcher {
211220

212221
bool hasBlock() const { return HasBlock; }
213222

223+
bool isSingleRelease(SILArgument *Arg) const {
224+
auto Iter = ArgInstMap.find(Arg);
225+
assert(Iter != ArgInstMap.end() && "Failed to get release list for argument");
226+
return Iter->second.size() == 1;
227+
}
228+
214229
SILInstruction *getSingleReleaseForArgument(SILArgument *Arg) {
215230
auto I = ArgInstMap.find(Arg);
216231
if (I == ArgInstMap.end())
217232
return nullptr;
218-
if (I->second.size() > 1)
233+
if (!isSingleRelease(Arg))
219234
return nullptr;
220235
return *I->second.begin();
221236
}

lib/SILOptimizer/Analysis/ARCAnalysis.cpp

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -621,9 +621,10 @@ findMatchingRetainsInner(SILBasicBlock *BB, SILValue V) {
621621
return std::make_pair(FindRetainKind::None, nullptr);
622622
}
623623

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) {
627628
recompute();
628629
}
629630

@@ -674,26 +675,52 @@ isRedundantRelease(ReleaseList Insts, SILValue Base, SILValue Derived) {
674675

675676
bool
676677
ConsumedArgToEpilogueReleaseMatcher::
677-
releaseAllNonTrivials(ReleaseList Insts, SILValue Base) {
678+
releaseArgument(ReleaseList Insts, SILValue Arg) {
678679
// Reason about whether all parts are released.
679680
SILModule *Mod = &(*Insts.begin())->getModule();
680681

681682
// These are the list of SILValues that are actually released.
682683
ProjectionPathSet Paths;
683684
for (auto &I : Insts) {
684-
auto PP = ProjectionPath::getProjectionPath(Base, I->getOperand(0));
685+
auto PP = ProjectionPath::getProjectionPath(Arg, I->getOperand(0));
685686
if (!PP)
686687
return false;
687688
Paths.insert(PP.getValue());
688689
}
689690

690691
// Is there an uncovered non-trivial type.
691-
return !ProjectionPath::hasUncoveredNonTrivials(Base->getType(), Mod, Paths);
692+
return !ProjectionPath::hasUncoveredNonTrivials(Arg->getType(), Mod, Paths);
692693
}
693694

694695
void
695696
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) {
697724
// Iterate over the instructions post-order and find final releases
698725
// associated with each arguments.
699726
//
@@ -734,7 +761,7 @@ findMatchingReleases(SILBasicBlock *BB) {
734761
auto *Arg = dyn_cast<SILArgument>(Op);
735762
// If this is not a SILArgument, maybe it is a part of a SILArgument.
736763
// This is possible after we expand release instructions in SILLowerAgg pass.
737-
if (!Arg) {
764+
if (!Arg) {
738765
Arg = dyn_cast<SILArgument>(stripValueProjections(OrigOp));
739766
}
740767

@@ -769,29 +796,16 @@ findMatchingReleases(SILBasicBlock *BB) {
769796
// Record it.
770797
Iter->second.push_back(Target);
771798
}
799+
}
772800

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();
795809
}
796810

797811
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)