Skip to content

Commit 166e876

Browse files
authored
Merge pull request #4744 from trentxintong/wireup-FSO
Turn epilogue retain/release matcher to an Analysis
2 parents 8d029be + 5ab532d commit 166e876

File tree

8 files changed

+499
-365
lines changed

8 files changed

+499
-365
lines changed

include/swift/SILOptimizer/Analysis/ARCAnalysis.h

Lines changed: 0 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -395,195 +395,4 @@ SILInstruction *findReleaseToMatchUnsafeGuaranteedValue(
395395

396396
} // end namespace swift
397397

398-
399-
namespace swift {
400-
401-
/// EpilogueARCBlockState - Keep track of whether an epilogue ARC instruction
402-
/// has been found.
403-
struct EpilogueARCBlockState {
404-
/// Keep track of whether an epilogue release has been found before and after
405-
/// this basic block.
406-
bool BBSetIn;
407-
/// The basic block local SILValue we are interested to find epilogue ARC in.
408-
SILValue LocalArg;
409-
/// Constructor, we only compute epilogue ARC instruction for 1 argument at
410-
/// a time.
411-
/// Optimistic data flow.
412-
EpilogueARCBlockState() { BBSetIn = true; LocalArg = SILValue(); }
413-
};
414-
415-
/// EpilogueARCContext - This class implements a data flow with which epilogue
416-
/// retains or releases for a SILValue are found.
417-
///
418-
/// NOTE:
419-
/// In case of release finder, this function assumes the SILArgument has
420-
/// @owned semantic.
421-
/// In case of retain finder, this class assumes Arg is one of the return value
422-
/// of the function.
423-
class EpilogueARCContext {
424-
public:
425-
enum EpilogueARCKind { Retain = 0, Release = 1 };
426-
427-
private:
428-
// Are we finding retains or releases.
429-
EpilogueARCKind Kind;
430-
431-
// The argument we are looking for epilogue ARC instruction for.
432-
SILValue Arg;
433-
434-
/// The allocator we are currently using.
435-
llvm::SpecificBumpPtrAllocator<EpilogueARCBlockState> BPA;
436-
437-
/// Current function we are analyzing.
438-
SILFunction *F;
439-
440-
/// Current post-order we are using.
441-
PostOrderFunctionInfo *PO;
442-
443-
/// Current alias analysis we are using.
444-
AliasAnalysis *AA;
445-
446-
/// Current rc-identity we are using.
447-
RCIdentityFunctionInfo *RCFI;
448-
449-
/// The epilogue retains or releases.
450-
llvm::SmallSetVector<SILInstruction *, 1> EpilogueARCInsts;
451-
452-
/// All the retain/release block state for all the basic blocks in the function.
453-
llvm::DenseMap<SILBasicBlock *, EpilogueARCBlockState *> EpilogueARCBlockStates;
454-
455-
/// The exit blocks of the function.
456-
llvm::SmallPtrSet<SILBasicBlock *, 2> ExitBlocks;
457-
458-
/// Return true if this is a function exitting block this epilogue ARC
459-
/// matcher is interested in.
460-
bool isInterestedFunctionExitingBlock(SILBasicBlock *BB) {
461-
if (EpilogueARCKind::Release == Kind)
462-
return BB->getTerminator()->isFunctionExiting();
463-
464-
return BB->getTerminator()->isFunctionExiting() &&
465-
BB->getTerminator()->getTermKind() != TermKind::ThrowInst;
466-
}
467-
468-
/// Return true if this is a function exit block.
469-
bool isExitBlock(SILBasicBlock *BB) {
470-
return ExitBlocks.count(BB);
471-
}
472-
473-
/// Return true if this is a retain instruction.
474-
bool isRetainInstruction(SILInstruction *II) {
475-
return isa<RetainValueInst>(II) || isa<StrongRetainInst>(II);
476-
}
477-
478-
/// Return true if this is a release instruction.
479-
bool isReleaseInstruction(SILInstruction *II) {
480-
return isa<ReleaseValueInst>(II) || isa<StrongReleaseInst>(II);
481-
}
482-
483-
SILValue getArg(SILBasicBlock *B) {
484-
SILValue A = EpilogueARCBlockStates[B]->LocalArg;
485-
if (A)
486-
return A;
487-
return Arg;
488-
}
489-
490-
public:
491-
/// Constructor.
492-
EpilogueARCContext(EpilogueARCKind Kind, SILValue Arg, SILFunction *F,
493-
PostOrderFunctionInfo *PO, AliasAnalysis *AA,
494-
RCIdentityFunctionInfo *RCFI)
495-
: Kind(Kind), Arg(Arg), F(F), PO(PO), AA(AA), RCFI(RCFI) {}
496-
497-
/// Run the data flow to find the epilogue retains or releases.
498-
bool run() {
499-
// Initialize the epilogue arc data flow context.
500-
initializeDataflow();
501-
// Converge the data flow.
502-
if (!convergeDataflow())
503-
return false;
504-
// Lastly, find the epilogue ARC instructions.
505-
return computeEpilogueARC();
506-
}
507-
508-
/// Reset the epilogue arc instructions.
509-
void resetEpilogueARCInsts() { EpilogueARCInsts.clear(); }
510-
llvm::SmallSetVector<SILInstruction *, 1> getEpilogueARCInsts() {
511-
return EpilogueARCInsts;
512-
}
513-
514-
/// Initialize the data flow.
515-
void initializeDataflow();
516-
517-
/// Keep iterating until the data flow is converged.
518-
bool convergeDataflow();
519-
520-
/// Find the epilogue ARC instructions.
521-
bool computeEpilogueARC();
522-
523-
/// This instruction prevents looking further for epilogue retains on the
524-
/// current path.
525-
bool mayBlockEpilogueRetain(SILInstruction *II, SILValue Ptr) {
526-
// reference decrementing instruction prevents any retain to be identified as
527-
// epilogue retains.
528-
if (mayDecrementRefCount(II, Ptr, AA))
529-
return true;
530-
// Handle self-recursion. A self-recursion can be considered a +1 on the
531-
// current argument.
532-
if (ApplyInst *AI = dyn_cast<ApplyInst>(II))
533-
if (AI->getCalleeFunction() == II->getParent()->getParent())
534-
return true;
535-
return false;
536-
}
537-
538-
/// This instruction prevents looking further for epilogue releases on the
539-
/// current path.
540-
bool mayBlockEpilogueRelease(SILInstruction *II, SILValue Ptr) {
541-
// Check whether this instruction read reference count, i.e. uniqueness
542-
// check. Moving release past that may result in additional COW.
543-
if (II->mayReleaseOrReadRefCount())
544-
return true;
545-
return false;
546-
}
547-
548-
/// Does this instruction block the interested ARC instruction ?
549-
bool mayBlockEpilogueARC(SILInstruction *II, SILValue Ptr) {
550-
if (Kind == EpilogueARCKind::Retain)
551-
return mayBlockEpilogueRetain(II, Ptr);
552-
return mayBlockEpilogueRelease(II, Ptr);
553-
}
554-
555-
/// This is the type of instructions the data flow is interested in.
556-
bool isInterestedInstruction(SILInstruction *II) {
557-
// We are checking for release.
558-
if (Kind == EpilogueARCKind::Release)
559-
return isReleaseInstruction(II) &&
560-
RCFI->getRCIdentityRoot(II->getOperand(0)) ==
561-
RCFI->getRCIdentityRoot(getArg(II->getParent()));
562-
// We are checking for retain. If this is a self-recursion. call
563-
// to the function (which returns an owned value) can be treated as
564-
// the retain instruction.
565-
if (ApplyInst *AI = dyn_cast<ApplyInst>(II))
566-
if (AI->getCalleeFunction() == II->getParent()->getParent())
567-
return true;
568-
// Check whether this is a retain instruction and the argument it
569-
// retains.
570-
return isRetainInstruction(II) &&
571-
RCFI->getRCIdentityRoot(II->getOperand(0)) ==
572-
RCFI->getRCIdentityRoot(getArg(II->getParent()));
573-
}
574-
};
575-
576-
/// Compute the epilogue ARC instructions for a given SILValue. Return an
577-
/// empty set if no epilogue ARC instructions can be found.
578-
///
579-
/// NOTE: This function assumes Arg is has @owned semantic.
580-
llvm::SmallSetVector<SILInstruction *, 1>
581-
computeEpilogueARCInstructions(EpilogueARCContext::EpilogueARCKind Kind,
582-
SILValue Arg, SILFunction *F,
583-
PostOrderFunctionInfo *PO, AliasAnalysis *AA,
584-
RCIdentityFunctionInfo *RCFI);
585-
586-
} // end namespace swift
587-
588-
589398
#endif

include/swift/SILOptimizer/Analysis/Analysis.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ANALYSIS(Caller)
2929
ANALYSIS(ClassHierarchy)
3030
ANALYSIS(Destructor)
3131
ANALYSIS(Dominance)
32+
ANALYSIS(EpilogueARC)
3233
ANALYSIS(Escape)
3334
ANALYSIS(InductionVariable)
3435
ANALYSIS(Loop)

0 commit comments

Comments
 (0)