mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Cleanup and document SIL memory behavior APIs.
This is code that I am fairly familiar with but it still took a day of investigation to figure out how it is supposed to be used now in the presence of bridging. This primarily involved ruling out the possibity that the mid-level Swift APIs could at some point call into the lower-level C++ APIs. The biggest problem was that AliasAnalysis::getMemoryBehaviorOfInst() was declared as a public interface, and it's name indicates that it computes the memory behavior. But it is just a wrapper around a Swift API and never actually calls into any of the C++ logic that is responsible for computing memory behavior!
This commit is contained in:
@@ -137,8 +137,13 @@
|
|||||||
/// NAME is the name of the instruction in SIL assembly.
|
/// NAME is the name of the instruction in SIL assembly.
|
||||||
/// The argument will be a bare identifier, not a string literal.
|
/// The argument will be a bare identifier, not a string literal.
|
||||||
///
|
///
|
||||||
/// MEMBEHAVIOR is an enum value that reflects the memory behavior of
|
/// MEMBEHAVIOR is an enum value that reflects the memory behavior of the
|
||||||
/// the instruction.
|
/// instruction. It is only used in the implementation of
|
||||||
|
/// SILInstruction::getMemoryBehavior(). Memory behavior is relative, so
|
||||||
|
/// whenever possible, clients should instead use
|
||||||
|
/// AliasAnalysis::computeMemoryBehavior(SILInstruction, SILValue) which only
|
||||||
|
/// defaults to SILInstruction::getMemoryBehavior() when AliasAnalysis cannot
|
||||||
|
/// disambiguate the instruction's effects from the value of interest.
|
||||||
///
|
///
|
||||||
/// MAYRELEASE indicates whether the execution of the
|
/// MAYRELEASE indicates whether the execution of the
|
||||||
/// instruction may result in memory being released.
|
/// instruction may result in memory being released.
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ namespace swift {
|
|||||||
|
|
||||||
/// This class is a simple wrapper around an alias analysis cache. This is
|
/// This class is a simple wrapper around an alias analysis cache. This is
|
||||||
/// needed since we do not have an "analysis" infrastructure.
|
/// needed since we do not have an "analysis" infrastructure.
|
||||||
|
///
|
||||||
|
/// This wrapper sits above the SwiftCompilerSource implementation of
|
||||||
|
/// AliasAnalysis. The implementation calls into AliasAnalysis.swift via
|
||||||
|
/// BridgedAliasAnalysis whenever the result may depend on escape analysis.
|
||||||
class AliasAnalysis {
|
class AliasAnalysis {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -159,14 +163,24 @@ public:
|
|||||||
return alias(V1, V2, TBAAType1, TBAAType2) == AliasResult::MayAlias;
|
return alias(V1, V2, TBAAType1, TBAAType2) == AliasResult::MayAlias;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Use the alias analysis to determine the memory behavior of Inst with
|
/// Compute the effects of Inst's memory behavior on the memory pointed to by
|
||||||
/// respect to V.
|
/// the value V.
|
||||||
|
///
|
||||||
|
/// This is the top-level API for memory behavior.
|
||||||
|
///
|
||||||
|
/// 1. MemoryBehaviorVisitor overrides select instruction types. Types that
|
||||||
|
/// have no override default to SILInstruction::getMemoryBehavior(), which is
|
||||||
|
/// not specific to the memory pointed to by V.
|
||||||
|
///
|
||||||
|
/// 2. For instruction types overridden by MemoryBehaviorVisitor, this uses
|
||||||
|
/// alias analysis to disambiguate the Inst's memory effects from the memory
|
||||||
|
/// pointed to by value V. 'mayAlias' is used for memory operations and
|
||||||
|
/// 'getMemoryEffectOnEscapedAddress' is used for calls and releases.
|
||||||
|
///
|
||||||
|
/// 3. For calls, alias analysis uses callee analysis to retrieve function
|
||||||
|
/// side effects which provides the memory behavior of each argument.
|
||||||
MemoryBehavior computeMemoryBehavior(SILInstruction *Inst, SILValue V);
|
MemoryBehavior computeMemoryBehavior(SILInstruction *Inst, SILValue V);
|
||||||
|
|
||||||
/// Use the alias analysis to determine the memory behavior of Inst with
|
|
||||||
/// respect to V.
|
|
||||||
MemoryBehavior computeMemoryBehaviorInner(SILInstruction *Inst, SILValue V);
|
|
||||||
|
|
||||||
/// Returns true if \p Inst may read from memory at address \p V.
|
/// Returns true if \p Inst may read from memory at address \p V.
|
||||||
///
|
///
|
||||||
/// For details see MemoryBehavior::MayRead.
|
/// For details see MemoryBehavior::MayRead.
|
||||||
@@ -203,20 +217,37 @@ public:
|
|||||||
/// Returns true if \p Ptr may be released by the builtin \p BI.
|
/// Returns true if \p Ptr may be released by the builtin \p BI.
|
||||||
bool canBuiltinDecrementRefCount(BuiltinInst *BI, SILValue Ptr);
|
bool canBuiltinDecrementRefCount(BuiltinInst *BI, SILValue Ptr);
|
||||||
|
|
||||||
/// Returns true if the address(es of) `addr` can escape to `toInst`.
|
int getEstimatedFunctionSize(SILValue valueInFunction);
|
||||||
MemoryBehavior getMemoryBehaviorOfInst(SILValue addr, SILInstruction *toInst);
|
|
||||||
|
|
||||||
/// Returns true if the object(s of) `obj` can escape to `toInst`.
|
/// Returns true if the object(s of) `obj` can escape to `toInst`.
|
||||||
|
///
|
||||||
|
/// Special entry point into BridgedAliasAnalysis (escape analysis) for use in
|
||||||
|
/// ARC analysis.
|
||||||
bool isObjectReleasedByInst(SILValue obj, SILInstruction *toInst);
|
bool isObjectReleasedByInst(SILValue obj, SILInstruction *toInst);
|
||||||
|
|
||||||
/// Is the `addr` within all reachable objects/addresses, when start walking
|
/// Is the `addr` within all reachable objects/addresses, when start walking
|
||||||
/// from `obj`?
|
/// from `obj`?
|
||||||
|
///
|
||||||
|
/// Special entry point into BridgedAliasAnalysis (escape analysis) for use in
|
||||||
|
/// ARC analysis.
|
||||||
bool isAddrVisibleFromObject(SILValue addr, SILValue obj);
|
bool isAddrVisibleFromObject(SILValue addr, SILValue obj);
|
||||||
|
|
||||||
|
/// MARK: implementation helpers for MemBehaviorVisitor.
|
||||||
|
|
||||||
|
/// If the address(es of) `addr` can escape to `toInst` (based on escape
|
||||||
|
/// analysis), return the memory effect of `toInst` on the escaped memory.
|
||||||
|
///
|
||||||
|
/// This should not be called directly; it is an implementation helper for
|
||||||
|
/// querying escape analysis.
|
||||||
|
MemoryBehavior getMemoryEffectOnEscapedAddress(SILValue addr, SILInstruction *toInst);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// Use the alias analysis to determine the memory behavior of Inst with
|
||||||
|
/// respect to V.
|
||||||
|
MemoryBehavior computeMemoryBehaviorInner(SILInstruction *Inst, SILValue V);
|
||||||
|
|
||||||
/// Returns true if `lhs` can reference the same field as `rhs`.
|
/// Returns true if `lhs` can reference the same field as `rhs`.
|
||||||
bool canReferenceSameField(SILValue lhs, SILValue rhs);
|
bool canReferenceSameField(SILValue lhs, SILValue rhs);
|
||||||
|
|
||||||
int getEstimatedFunctionSize(SILValue valueInFunction);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -711,7 +711,7 @@ void BridgedAliasAnalysis::registerAnalysis(GetMemEffectFn getMemEffectsFn,
|
|||||||
canReferenceSameFieldFunction = canReferenceSameFieldFn;
|
canReferenceSameFieldFunction = canReferenceSameFieldFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBehavior AliasAnalysis::getMemoryBehaviorOfInst(
|
MemoryBehavior AliasAnalysis::getMemoryEffectOnEscapedAddress(
|
||||||
SILValue addr, SILInstruction *toInst) {
|
SILValue addr, SILInstruction *toInst) {
|
||||||
if (getMemEffectsFunction) {
|
if (getMemEffectsFunction) {
|
||||||
return (MemoryBehavior)getMemEffectsFunction({PM->getSwiftPassInvocation()}, {addr},
|
return (MemoryBehavior)getMemEffectsFunction({PM->getSwiftPassInvocation()}, {addr},
|
||||||
|
|||||||
@@ -317,50 +317,50 @@ MemBehavior MemoryBehaviorVisitor::visitMarkUnresolvedMoveAddrInst(
|
|||||||
MemBehavior MemoryBehaviorVisitor::visitBuiltinInst(BuiltinInst *BI) {
|
MemBehavior MemoryBehaviorVisitor::visitBuiltinInst(BuiltinInst *BI) {
|
||||||
MemBehavior mb = BI->getMemoryBehavior();
|
MemBehavior mb = BI->getMemoryBehavior();
|
||||||
if (mb != MemBehavior::None) {
|
if (mb != MemBehavior::None) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, BI);
|
return AA->getMemoryEffectOnEscapedAddress(V, BI);
|
||||||
}
|
}
|
||||||
return MemBehavior::None;
|
return MemBehavior::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitTryApplyInst(TryApplyInst *AI) {
|
MemBehavior MemoryBehaviorVisitor::visitTryApplyInst(TryApplyInst *AI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, AI);
|
return AA->getMemoryEffectOnEscapedAddress(V, AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
|
MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, AI);
|
return AA->getMemoryEffectOnEscapedAddress(V, AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitBeginApplyInst(BeginApplyInst *AI) {
|
MemBehavior MemoryBehaviorVisitor::visitBeginApplyInst(BeginApplyInst *AI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, AI);
|
return AA->getMemoryEffectOnEscapedAddress(V, AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitEndApplyInst(EndApplyInst *EAI) {
|
MemBehavior MemoryBehaviorVisitor::visitEndApplyInst(EndApplyInst *EAI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, EAI->getBeginApply());
|
return AA->getMemoryEffectOnEscapedAddress(V, EAI->getBeginApply());
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitAbortApplyInst(AbortApplyInst *AAI) {
|
MemBehavior MemoryBehaviorVisitor::visitAbortApplyInst(AbortApplyInst *AAI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, AAI->getBeginApply());
|
return AA->getMemoryEffectOnEscapedAddress(V, AAI->getBeginApply());
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior
|
MemBehavior
|
||||||
MemoryBehaviorVisitor::visitStrongReleaseInst(StrongReleaseInst *SI) {
|
MemoryBehaviorVisitor::visitStrongReleaseInst(StrongReleaseInst *SI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, SI);
|
return AA->getMemoryEffectOnEscapedAddress(V, SI);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
|
#define ALWAYS_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
|
||||||
MemBehavior \
|
MemBehavior \
|
||||||
MemoryBehaviorVisitor::visit##Name##ReleaseInst(Name##ReleaseInst *SI) { \
|
MemoryBehaviorVisitor::visit##Name##ReleaseInst(Name##ReleaseInst *SI) { \
|
||||||
return AA->getMemoryBehaviorOfInst(V, SI); \
|
return AA->getMemoryEffectOnEscapedAddress(V, SI); \
|
||||||
}
|
}
|
||||||
#include "swift/AST/ReferenceStorage.def"
|
#include "swift/AST/ReferenceStorage.def"
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitReleaseValueInst(ReleaseValueInst *SI) {
|
MemBehavior MemoryBehaviorVisitor::visitReleaseValueInst(ReleaseValueInst *SI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, SI);
|
return AA->getMemoryEffectOnEscapedAddress(V, SI);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior
|
MemBehavior
|
||||||
MemoryBehaviorVisitor::visitDestroyValueInst(DestroyValueInst *DVI) {
|
MemoryBehaviorVisitor::visitDestroyValueInst(DestroyValueInst *DVI) {
|
||||||
return AA->getMemoryBehaviorOfInst(V, DVI);
|
return AA->getMemoryEffectOnEscapedAddress(V, DVI);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitSetDeallocatingInst(SetDeallocatingInst *SDI) {
|
MemBehavior MemoryBehaviorVisitor::visitSetDeallocatingInst(SetDeallocatingInst *SDI) {
|
||||||
|
|||||||
Reference in New Issue
Block a user