Skip to content

Commit 39b966a

Browse files
authored
Merge pull request #34543 from gottesmm/pr-0797da971faacb826fafd0134436240a2e678ae7
[membehavior] Fix base memory behavior/releasing of Load/Store for ownership
2 parents 0598957 + c3681a6 commit 39b966a

File tree

4 files changed

+80
-16
lines changed

4 files changed

+80
-16
lines changed

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
592592

593593
// Accessing memory
594594
SINGLE_VALUE_INST(LoadInst, load,
595-
SingleValueInstruction, MayRead, DoesNotRelease)
595+
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
596596
SINGLE_VALUE_INST(LoadBorrowInst, load_borrow,
597597
SingleValueInstruction, MayRead, DoesNotRelease)
598598
SINGLE_VALUE_INST(BeginBorrowInst, begin_borrow,
@@ -852,7 +852,7 @@ NON_VALUE_INST(BeginUnpairedAccessInst, begin_unpaired_access,
852852
NON_VALUE_INST(EndUnpairedAccessInst, end_unpaired_access,
853853
SILInstruction, MayHaveSideEffects, DoesNotRelease)
854854
NON_VALUE_INST(StoreInst, store,
855-
SILInstruction, MayWrite, DoesNotRelease)
855+
SILInstruction, MayHaveSideEffects, MayRelease)
856856
NON_VALUE_INST(AssignInst, assign,
857857
SILInstruction, MayWrite, DoesNotRelease)
858858
NON_VALUE_INST(AssignByWrapperInst, assign_by_wrapper,

lib/SIL/IR/SILInstruction.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,36 @@ SILInstruction::MemoryBehavior SILInstruction::getMemoryBehavior() const {
10291029
MemoryBehavior::MayHaveSideEffects;
10301030
}
10311031

1032+
if (auto *li = dyn_cast<LoadInst>(this)) {
1033+
switch (li->getOwnershipQualifier()) {
1034+
case LoadOwnershipQualifier::Unqualified:
1035+
case LoadOwnershipQualifier::Trivial:
1036+
return MemoryBehavior::MayRead;
1037+
case LoadOwnershipQualifier::Take:
1038+
// Take deinitializes the underlying memory. Until we separate notions of
1039+
// memory writing from deinitialization (since a take doesn't actually
1040+
// write to the memory), lets be conservative and treat it as may read
1041+
// write.
1042+
return MemoryBehavior::MayReadWrite;
1043+
case LoadOwnershipQualifier::Copy:
1044+
return MemoryBehavior::MayHaveSideEffects;
1045+
}
1046+
llvm_unreachable("Covered switch isn't covered?!");
1047+
}
1048+
1049+
if (auto *si = dyn_cast<StoreInst>(this)) {
1050+
switch (si->getOwnershipQualifier()) {
1051+
case StoreOwnershipQualifier::Unqualified:
1052+
case StoreOwnershipQualifier::Trivial:
1053+
case StoreOwnershipQualifier::Init:
1054+
return MemoryBehavior::MayWrite;
1055+
case StoreOwnershipQualifier::Assign:
1056+
// For the release.
1057+
return MemoryBehavior::MayHaveSideEffects;
1058+
}
1059+
llvm_unreachable("Covered switch isn't covered?!");
1060+
}
1061+
10321062
switch (getKind()) {
10331063
#define FULL_INST(CLASS, TEXTUALNAME, PARENT, MEMBEHAVIOR, RELEASINGBEHAVIOR) \
10341064
case SILInstructionKind::CLASS: \
@@ -1138,6 +1168,18 @@ bool SILInstruction::mayRelease() const {
11381168
}
11391169
return true;
11401170
}
1171+
case SILInstructionKind::StoreInst:
1172+
switch (cast<StoreInst>(this)->getOwnershipQualifier()) {
1173+
case StoreOwnershipQualifier::Unqualified:
1174+
case StoreOwnershipQualifier::Init:
1175+
case StoreOwnershipQualifier::Trivial:
1176+
return false;
1177+
case StoreOwnershipQualifier::Assign:
1178+
// Assign destroys the old value that was in the memory location before we
1179+
// write the new value into the location.
1180+
return true;
1181+
}
1182+
llvm_unreachable("Covered switch isn't covered?!");
11411183
}
11421184
}
11431185

lib/SILOptimizer/Analysis/MemoryBehavior.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,15 @@ MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
242242
if (!mayAlias(LI->getOperand()))
243243
return MemBehavior::None;
244244

245-
// A take is modelled as a write. See MemoryBehavior::MayWrite.
246-
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
247-
return MemBehavior::MayReadWrite;
248-
249245
LLVM_DEBUG(llvm::dbgs() << " Could not prove that load inst does not alias "
250-
"pointer. Returning may read.\n");
246+
"pointer. ");
247+
248+
if (LI->getOwnershipQualifier() == LoadOwnershipQualifier::Take) {
249+
LLVM_DEBUG(llvm::dbgs() << "Is a take so return MayReadWrite.\n");
250+
return MemBehavior::MayReadWrite;
251+
}
252+
253+
LLVM_DEBUG(llvm::dbgs() << "Not a take so returning MayRead.\n");
251254
return MemBehavior::MayRead;
252255
}
253256

@@ -257,15 +260,17 @@ MemBehavior MemoryBehaviorVisitor::visitStoreInst(StoreInst *SI) {
257260
if (isLetValue() && (getAccessBase(SI->getDest()) != getValueAddress())) {
258261
return MemBehavior::None;
259262
}
260-
// If the store dest cannot alias the pointer in question, then the
261-
// specified value cannot be modified by the store.
262-
if (!mayAlias(SI->getDest()))
263+
// If the store dest cannot alias the pointer in question and we are not
264+
// releasing anything due to an assign, then the specified value cannot be
265+
// modified by the store.
266+
if (!mayAlias(SI->getDest()) &&
267+
SI->getOwnershipQualifier() != StoreOwnershipQualifier::Assign)
263268
return MemBehavior::None;
264269

265270
// Otherwise, a store just writes.
266271
LLVM_DEBUG(llvm::dbgs() << " Could not prove store does not alias inst. "
267-
"Returning MayWrite.\n");
268-
return MemBehavior::MayWrite;
272+
"Returning default mem behavior.\n");
273+
return SI->getMemoryBehavior();
269274
}
270275

271276
MemBehavior MemoryBehaviorVisitor::visitCopyAddrInst(CopyAddrInst *CAI) {

lib/SILOptimizer/Analysis/SideEffectAnalysis.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -539,12 +539,29 @@ void FunctionSideEffects::analyzeInstruction(SILInstruction *I) {
539539
true;
540540
Traps = true;
541541
return;
542-
case SILInstructionKind::LoadInst:
543-
getEffectsOn(cast<LoadInst>(I)->getOperand())->Reads = true;
542+
case SILInstructionKind::LoadBorrowInst: {
543+
auto *effects = getEffectsOn(cast<LoadBorrowInst>(I)->getOperand());
544+
effects->Reads = true;
544545
return;
545-
case SILInstructionKind::StoreInst:
546-
getEffectsOn(cast<StoreInst>(I)->getDest())->Writes = true;
546+
}
547+
case SILInstructionKind::LoadInst: {
548+
auto *li = cast<LoadInst>(I);
549+
auto *effects = getEffectsOn(cast<LoadInst>(I)->getOperand());
550+
effects->Reads = true;
551+
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Take)
552+
effects->Writes = true;
553+
if (li->getOwnershipQualifier() == LoadOwnershipQualifier::Copy)
554+
effects->Retains = true;
555+
return;
556+
}
557+
case SILInstructionKind::StoreInst: {
558+
auto *si = cast<StoreInst>(I);
559+
auto *effects = getEffectsOn(si->getDest());
560+
effects->Writes = true;
561+
if (si->getOwnershipQualifier() == StoreOwnershipQualifier::Assign)
562+
effects->Releases = true;
547563
return;
564+
}
548565
case SILInstructionKind::CondFailInst:
549566
Traps = true;
550567
return;

0 commit comments

Comments
 (0)