mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[membehavior] Fix base memory behavior/releasing of Load/Store for ownership.
load, store in ossa can have side-effects and stores can release. Specifically: Memory Behavior --------------- * Load: unqualified, trivial, take have a read side-effect, but copy retains so has side-effects. * Store: unqualified, trivial, init may write but assign releases so it may have side-effects. Release Behavior ---------------- * Load: No changes. * Store: May release if store has assign as an ownership qualifier.
This commit is contained in:
@@ -592,7 +592,7 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
|
|||||||
|
|
||||||
// Accessing memory
|
// Accessing memory
|
||||||
SINGLE_VALUE_INST(LoadInst, load,
|
SINGLE_VALUE_INST(LoadInst, load,
|
||||||
SingleValueInstruction, MayRead, DoesNotRelease)
|
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
|
||||||
SINGLE_VALUE_INST(LoadBorrowInst, load_borrow,
|
SINGLE_VALUE_INST(LoadBorrowInst, load_borrow,
|
||||||
SingleValueInstruction, MayRead, DoesNotRelease)
|
SingleValueInstruction, MayRead, DoesNotRelease)
|
||||||
SINGLE_VALUE_INST(BeginBorrowInst, begin_borrow,
|
SINGLE_VALUE_INST(BeginBorrowInst, begin_borrow,
|
||||||
@@ -852,7 +852,7 @@ NON_VALUE_INST(BeginUnpairedAccessInst, begin_unpaired_access,
|
|||||||
NON_VALUE_INST(EndUnpairedAccessInst, end_unpaired_access,
|
NON_VALUE_INST(EndUnpairedAccessInst, end_unpaired_access,
|
||||||
SILInstruction, MayHaveSideEffects, DoesNotRelease)
|
SILInstruction, MayHaveSideEffects, DoesNotRelease)
|
||||||
NON_VALUE_INST(StoreInst, store,
|
NON_VALUE_INST(StoreInst, store,
|
||||||
SILInstruction, MayWrite, DoesNotRelease)
|
SILInstruction, MayHaveSideEffects, MayRelease)
|
||||||
NON_VALUE_INST(AssignInst, assign,
|
NON_VALUE_INST(AssignInst, assign,
|
||||||
SILInstruction, MayWrite, DoesNotRelease)
|
SILInstruction, MayWrite, DoesNotRelease)
|
||||||
NON_VALUE_INST(AssignByWrapperInst, assign_by_wrapper,
|
NON_VALUE_INST(AssignByWrapperInst, assign_by_wrapper,
|
||||||
|
|||||||
@@ -1029,6 +1029,36 @@ SILInstruction::MemoryBehavior SILInstruction::getMemoryBehavior() const {
|
|||||||
MemoryBehavior::MayHaveSideEffects;
|
MemoryBehavior::MayHaveSideEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (auto *li = dyn_cast<LoadInst>(this)) {
|
||||||
|
switch (li->getOwnershipQualifier()) {
|
||||||
|
case LoadOwnershipQualifier::Unqualified:
|
||||||
|
case LoadOwnershipQualifier::Trivial:
|
||||||
|
return MemoryBehavior::MayRead;
|
||||||
|
case LoadOwnershipQualifier::Take:
|
||||||
|
// Take deinitializes the underlying memory. Until we separate notions of
|
||||||
|
// memory writing from deinitialization (since a take doesn't actually
|
||||||
|
// write to the memory), lets be conservative and treat it as may read
|
||||||
|
// write.
|
||||||
|
return MemoryBehavior::MayReadWrite;
|
||||||
|
case LoadOwnershipQualifier::Copy:
|
||||||
|
return MemoryBehavior::MayHaveSideEffects;
|
||||||
|
}
|
||||||
|
llvm_unreachable("Covered switch isn't covered?!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto *si = dyn_cast<StoreInst>(this)) {
|
||||||
|
switch (si->getOwnershipQualifier()) {
|
||||||
|
case StoreOwnershipQualifier::Unqualified:
|
||||||
|
case StoreOwnershipQualifier::Trivial:
|
||||||
|
case StoreOwnershipQualifier::Init:
|
||||||
|
return MemoryBehavior::MayWrite;
|
||||||
|
case StoreOwnershipQualifier::Assign:
|
||||||
|
// For the release.
|
||||||
|
return MemoryBehavior::MayHaveSideEffects;
|
||||||
|
}
|
||||||
|
llvm_unreachable("Covered switch isn't covered?!");
|
||||||
|
}
|
||||||
|
|
||||||
switch (getKind()) {
|
switch (getKind()) {
|
||||||
#define FULL_INST(CLASS, TEXTUALNAME, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
|
#define FULL_INST(CLASS, TEXTUALNAME, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
|
||||||
case SILInstructionKind::CLASS: \
|
case SILInstructionKind::CLASS: \
|
||||||
@@ -1138,6 +1168,18 @@ bool SILInstruction::mayRelease() const {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case SILInstructionKind::StoreInst:
|
||||||
|
switch (cast<StoreInst>(this)->getOwnershipQualifier()) {
|
||||||
|
case StoreOwnershipQualifier::Unqualified:
|
||||||
|
case StoreOwnershipQualifier::Init:
|
||||||
|
case StoreOwnershipQualifier::Trivial:
|
||||||
|
return false;
|
||||||
|
case StoreOwnershipQualifier::Assign:
|
||||||
|
// Assign destroys the old value that was in the memory location before we
|
||||||
|
// write the new value into the location.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
llvm_unreachable("Covered switch isn't covered?!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -242,12 +242,15 @@ MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
|
|||||||
if (!mayAlias(LI->getOperand()))
|
if (!mayAlias(LI->getOperand()))
|
||||||
return MemBehavior::None;
|
return MemBehavior::None;
|
||||||
|
|
||||||
// A take is modelled as a write. See MemoryBehavior::MayWrite.
|
|
||||||
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
|
|
||||||
return MemBehavior::MayReadWrite;
|
|
||||||
|
|
||||||
LLVM_DEBUG(llvm::dbgs() << " Could not prove that load inst does not alias "
|
LLVM_DEBUG(llvm::dbgs() << " Could not prove that load inst does not alias "
|
||||||
"pointer. Returning may read.\n");
|
"pointer. ");
|
||||||
|
|
||||||
|
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take) {
|
||||||
|
LLVM_DEBUG(llvm::dbgs() << "Is a take so return MayReadWrite.\n");
|
||||||
|
return MemBehavior::MayReadWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVM_DEBUG(llvm::dbgs() << "Not a take so returning MayRead.\n");
|
||||||
return MemBehavior::MayRead;
|
return MemBehavior::MayRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,15 +260,17 @@ MemBehavior MemoryBehaviorVisitor::visitStoreInst(StoreInst *SI) {
|
|||||||
if (isLetValue() && (getAccessBase(SI->getDest()) != getValueAddress())) {
|
if (isLetValue() && (getAccessBase(SI->getDest()) != getValueAddress())) {
|
||||||
return MemBehavior::None;
|
return MemBehavior::None;
|
||||||
}
|
}
|
||||||
// If the store dest cannot alias the pointer in question, then the
|
// If the store dest cannot alias the pointer in question and we are not
|
||||||
// specified value cannot be modified by the store.
|
// releasing anything due to an assign, then the specified value cannot be
|
||||||
if (!mayAlias(SI->getDest()))
|
// modified by the store.
|
||||||
|
if (!mayAlias(SI->getDest()) &&
|
||||||
|
SI->getOwnershipQualifier() != StoreOwnershipQualifier::Assign)
|
||||||
return MemBehavior::None;
|
return MemBehavior::None;
|
||||||
|
|
||||||
// Otherwise, a store just writes.
|
// Otherwise, a store just writes.
|
||||||
LLVM_DEBUG(llvm::dbgs() << " Could not prove store does not alias inst. "
|
LLVM_DEBUG(llvm::dbgs() << " Could not prove store does not alias inst. "
|
||||||
"Returning MayWrite.\n");
|
"Returning default mem behavior.\n");
|
||||||
return MemBehavior::MayWrite;
|
return SI->getMemoryBehavior();
|
||||||
}
|
}
|
||||||
|
|
||||||
MemBehavior MemoryBehaviorVisitor::visitCopyAddrInst(CopyAddrInst *CAI) {
|
MemBehavior MemoryBehaviorVisitor::visitCopyAddrInst(CopyAddrInst *CAI) {
|
||||||
|
|||||||
@@ -539,12 +539,29 @@ void FunctionSideEffects::analyzeInstruction(SILInstruction *I) {
|
|||||||
true;
|
true;
|
||||||
Traps = true;
|
Traps = true;
|
||||||
return;
|
return;
|
||||||
case SILInstructionKind::LoadInst:
|
case SILInstructionKind::LoadBorrowInst: {
|
||||||
getEffectsOn(cast<LoadInst>(I)->getOperand())->Reads = true;
|
auto *effects = getEffectsOn(cast<LoadBorrowInst>(I)->getOperand());
|
||||||
|
effects->Reads = true;
|
||||||
return;
|
return;
|
||||||
case SILInstructionKind::StoreInst:
|
}
|
||||||
getEffectsOn(cast<StoreInst>(I)->getDest())->Writes = true;
|
case SILInstructionKind::LoadInst: {
|
||||||
|
auto *li = cast<LoadInst>(I);
|
||||||
|
auto *effects = getEffectsOn(cast<LoadInst>(I)->getOperand());
|
||||||
|
effects->Reads = true;
|
||||||
|
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
|
||||||
|
effects->Writes = true;
|
||||||
|
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Copy)
|
||||||
|
effects->Retains = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
case SILInstructionKind::StoreInst: {
|
||||||
|
auto *si = cast<StoreInst>(I);
|
||||||
|
auto *effects = getEffectsOn(si->getDest());
|
||||||
|
effects->Writes = true;
|
||||||
|
if (si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign)
|
||||||
|
effects->Releases = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
case SILInstructionKind::CondFailInst:
|
case SILInstructionKind::CondFailInst:
|
||||||
Traps = true;
|
Traps = true;
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user