Skip to content

Commit af23d09

Browse files
committed
[arc] Clean up ConsumedArgToEpilogueReleaseMatcher so we can recompute if we need to.
This can happen if ARCSequenceOpts moves around retains, releases.
1 parent a7c8f19 commit af23d09

File tree

3 files changed

+46
-20
lines changed

3 files changed

+46
-20
lines changed

include/swift/SILAnalysis/ARCAnalysis.h

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,27 @@ valueHasARCDecrementOrCheckInInstructionRange(SILValue Op,
108108
///
109109
/// TODO: This really needs a better name.
110110
class ConsumedArgToEpilogueReleaseMatcher {
111+
public:
112+
enum class ExitKind { Return, Throw };
113+
114+
private:
115+
SILFunction *F;
116+
RCIdentityFunctionInfo *RCFI;
117+
ExitKind Kind;
111118
llvm::SmallMapVector<SILArgument *, SILInstruction *, 8> ArgInstMap;
119+
bool HasBlock = false;
112120

113121
public:
114-
/// Default constructor: does not find matching releases, so
115-
/// findMatchingReleases should be called explicitly.
116-
ConsumedArgToEpilogueReleaseMatcher() { }
117122

118123
/// Finds matching releases in the return block of the function \p F.
119-
ConsumedArgToEpilogueReleaseMatcher(RCIdentityFunctionInfo *RCIA,
120-
SILFunction *F);
124+
ConsumedArgToEpilogueReleaseMatcher(RCIdentityFunctionInfo *RCFI,
125+
SILFunction *F,
126+
ExitKind Kind = ExitKind::Return);
121127

122128
/// Finds matching releases in the provided block \p BB.
123-
void findMatchingReleases(RCIdentityFunctionInfo *RCIA, SILBasicBlock *BB);
129+
void findMatchingReleases(SILBasicBlock *BB);
130+
131+
bool hasBlock() const { return HasBlock; }
124132

125133
bool argumentHasRelease(SILArgument *Arg) const {
126134
return ArgInstMap.find(Arg) != ArgInstMap.end();
@@ -140,6 +148,9 @@ class ConsumedArgToEpilogueReleaseMatcher {
140148
return I->second;
141149
}
142150

151+
/// Recompute the mapping from argument to consumed arg.
152+
void recompute();
153+
143154
bool isReleaseMatchedToArgument(SILInstruction *Inst) const {
144155
auto Pred = [&Inst](const std::pair<SILArgument *,
145156
SILInstruction *> &P) -> bool {

lib/SILAnalysis/ARCAnalysis.cpp

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -508,17 +508,34 @@ mayGuaranteedUseValue(SILInstruction *User, SILValue Ptr, AliasAnalysis *AA) {
508508
// Owned Argument Utilities
509509
//===----------------------------------------------------------------------===//
510510

511-
ConsumedArgToEpilogueReleaseMatcher::
512-
ConsumedArgToEpilogueReleaseMatcher(RCIdentityFunctionInfo *RCIA,
513-
SILFunction *F) {
511+
ConsumedArgToEpilogueReleaseMatcher::ConsumedArgToEpilogueReleaseMatcher(
512+
RCIdentityFunctionInfo *RCFI, SILFunction *F, ExitKind Kind)
513+
: F(F), RCFI(RCFI), Kind(Kind) {
514+
recompute();
515+
}
516+
517+
void ConsumedArgToEpilogueReleaseMatcher::recompute() {
514518
// Find the return BB of F. If we fail, then bail.
515-
auto ReturnBB = F->findReturnBB();
516-
if (ReturnBB != F->end())
517-
findMatchingReleases(RCIA, &*ReturnBB);
519+
SILFunction::iterator BB;
520+
switch (Kind) {
521+
case ExitKind::Return:
522+
BB = F->findReturnBB();
523+
break;
524+
case ExitKind::Throw:
525+
BB = F->findThrowBB();
526+
break;
527+
}
528+
529+
if (BB == F->end()) {
530+
HasBlock = false;
531+
return;
532+
}
533+
HasBlock = true;
534+
findMatchingReleases(&*BB);
518535
}
519536

520-
void ConsumedArgToEpilogueReleaseMatcher::
521-
findMatchingReleases(RCIdentityFunctionInfo *RCIA, SILBasicBlock *BB) {
537+
void ConsumedArgToEpilogueReleaseMatcher::findMatchingReleases(
538+
SILBasicBlock *BB) {
522539
for (auto II = std::next(BB->rbegin()), IE = BB->rend();
523540
II != IE; ++II) {
524541
// If we do not have a release_value or strong_release...
@@ -536,7 +553,7 @@ findMatchingReleases(RCIdentityFunctionInfo *RCIA, SILBasicBlock *BB) {
536553
// Ok, we have a release_value or strong_release. Grab Target and find the
537554
// RC identity root of its operand.
538555
SILInstruction *Target = &*II;
539-
SILValue Op = RCIA->getRCIdentityRoot(Target->getOperand(0));
556+
SILValue Op = RCFI->getRCIdentityRoot(Target->getOperand(0));
540557

541558
// If Op is not a consumed argument, we must break since this is not an Op
542559
// that is a part of a return sequence. We are being conservative here since

lib/SILPasses/IPO/FunctionSignatureOpts.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -502,10 +502,8 @@ bool FunctionAnalyzer::analyze() {
502502
// A map from consumed SILArguments to the release associated with an
503503
// argument.
504504
ConsumedArgToEpilogueReleaseMatcher ArgToReturnReleaseMap(RCIA, F);
505-
ConsumedArgToEpilogueReleaseMatcher ArgToThrowReleaseMap;
506-
auto ThrowBBIter = F->findThrowBB();
507-
if (ThrowBBIter != F->end())
508-
ArgToThrowReleaseMap.findMatchingReleases(RCIA, &*ThrowBBIter);
505+
ConsumedArgToEpilogueReleaseMatcher ArgToThrowReleaseMap(
506+
RCIA, F, ConsumedArgToEpilogueReleaseMatcher::ExitKind::Throw);
509507

510508
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
511509
ArgumentDescriptor A(Allocator, Args[i]);
@@ -530,7 +528,7 @@ bool FunctionAnalyzer::analyze() {
530528

531529
// If the function has a throw block we must also find a matching
532530
// release in the throw block.
533-
if (ThrowBBIter == F->end() ||
531+
if (!ArgToThrowReleaseMap.hasBlock() ||
534532
(ReleaseInThrow = ArgToThrowReleaseMap.releaseForArgument(A.Arg))) {
535533

536534
// TODO: accept a second release in the throw block to let the

0 commit comments

Comments
 (0)