Skip to content

Commit ba001ec

Browse files
authored
Merge pull request #60467 from meg-gupta/fixstoreborrowsilgen
Fix store_borrow generation and improve its verification
2 parents ecccce6 + f374f2b commit ba001ec

File tree

62 files changed

+1180
-357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+1180
-357
lines changed

include/swift/SIL/MemAccessUtils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,6 +1691,10 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) {
16911691
if (isAccessStorageIdentityCast(svi))
16921692
return asImpl().visitStorageCast(svi, &svi->getAllOperands()[0],
16931693
AccessStorageCast::Identity);
1694+
if (auto *sbi = dyn_cast<StoreBorrowInst>(svi))
1695+
return asImpl().visitStorageCast(
1696+
svi, &sbi->getAllOperands()[CopyLikeInstruction::Dest],
1697+
AccessStorageCast::Identity);
16941698
}
16951699
switch (sourceAddr->getKind()) {
16961700
default:

include/swift/SIL/SILBuilder.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -774,7 +774,8 @@ class SILBuilder {
774774
}
775775

776776
void emitEndBorrowOperation(SILLocation loc, SILValue v) {
777-
if (!hasOwnership() || v->getOwnershipKind() == OwnershipKind::None)
777+
if (!hasOwnership() || (!v->getType().isAddress() &&
778+
v->getOwnershipKind() == OwnershipKind::None))
778779
return;
779780
createEndBorrow(loc, v);
780781
}

include/swift/SIL/SILCloner.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,12 +1160,10 @@ template <typename ImplClass>
11601160
void SILCloner<ImplClass>::visitStoreBorrowInst(StoreBorrowInst *Inst) {
11611161
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
11621162
if (!getBuilder().hasOwnership()) {
1163-
// TODO: Eliminate store_borrow result so we can use
1164-
// recordClonedInstruction. It is not "technically" necessary, but it is
1165-
// better from an invariant perspective.
11661163
getBuilder().createStore(
11671164
getOpLocation(Inst->getLoc()), getOpValue(Inst->getSrc()),
11681165
getOpValue(Inst->getDest()), StoreOwnershipQualifier::Unqualified);
1166+
mapValue(Inst, getOpValue(Inst->getDest()));
11691167
return;
11701168
}
11711169

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
//===--- ScopedAddressUtils.h ---------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_SIL_SCOPEDADDRESSUTILS_H
14+
#define SWIFT_SIL_SCOPEDADDRESSUTILS_H
15+
16+
#include "swift/Basic/Debug.h"
17+
#include "swift/Basic/LLVM.h"
18+
#include "swift/SIL/PrunedLiveness.h"
19+
#include "swift/SIL/SILBasicBlock.h"
20+
#include "swift/SIL/SILInstruction.h"
21+
#include "swift/SIL/SILValue.h"
22+
#include "swift/SILOptimizer/Utils/InstModCallbacks.h"
23+
24+
namespace swift {
25+
26+
class ScopedAddressValueKind {
27+
public:
28+
enum Kind : uint8_t {
29+
Invalid = 0,
30+
StoreBorrow,
31+
BeginAccess,
32+
};
33+
34+
private:
35+
Kind value;
36+
37+
public:
38+
static ScopedAddressValueKind get(SILValue value) {
39+
switch (value->getKind()) {
40+
default:
41+
return Kind::Invalid;
42+
case ValueKind::StoreBorrowInst:
43+
return Kind::StoreBorrow;
44+
case ValueKind::BeginAccessInst:
45+
return Kind::BeginAccess;
46+
}
47+
}
48+
49+
ScopedAddressValueKind(Kind newValue) : value(newValue) {}
50+
51+
operator Kind() const { return value; }
52+
53+
void print(llvm::raw_ostream &os) const;
54+
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
55+
};
56+
57+
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
58+
ScopedAddressValueKind kind);
59+
60+
struct ScopedAddressValue {
61+
SILValue value;
62+
ScopedAddressValueKind kind = ScopedAddressValueKind::Invalid;
63+
64+
ScopedAddressValue() = default;
65+
66+
explicit ScopedAddressValue(SILValue value) {
67+
kind = ScopedAddressValueKind::get(value);
68+
if (kind)
69+
this->value = value;
70+
}
71+
72+
operator bool() const {
73+
return kind != ScopedAddressValueKind::Invalid && value;
74+
}
75+
76+
void print(llvm::raw_ostream &os) const;
77+
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
78+
79+
// Helpers to allow a ScopedAddressValue to easily be used as a SILValue
80+
// programatically.
81+
SILValue operator->() { return value; }
82+
SILValue operator->() const { return value; }
83+
SILValue operator*() { return value; }
84+
SILValue operator*() const { return value; }
85+
86+
/// Returns true if \p op is a scope edning use of the scoped address value.
87+
bool isScopeEndingUse(Operand *op) const;
88+
/// Pass all scope ending instructions to the visitor.
89+
bool visitScopeEndingUses(function_ref<bool(Operand *)> visitor) const;
90+
/// Returns false, if liveness cannot be computed due to pointer escape or
91+
/// unkown address use. Add this scope's live blocks into the PrunedLiveness
92+
/// result.
93+
bool computeLiveness(PrunedLiveness &liveness) const;
94+
95+
/// Create appropriate scope ending instruction at \p insertPt.
96+
void createScopeEnd(SILBasicBlock::iterator insertPt, SILLocation loc) const;
97+
98+
/// Create scope ending instructions at \p liveness boundary.
99+
void endScopeAtLivenessBoundary(PrunedLiveness *liveness) const;
100+
};
101+
102+
llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
103+
const ScopedAddressValue &value);
104+
105+
/// Returns true if there are other store_borrows enclosed within a store_borrow
106+
/// \p sbi's scope
107+
bool hasOtherStoreBorrowsInLifetime(StoreBorrowInst *sbi,
108+
PrunedLiveness *liveness,
109+
DeadEndBlocks *deadEndBlocks);
110+
111+
/// Extend the store_borrow \p sbi's scope such that it encloses \p newUsers.
112+
bool extendStoreBorrow(StoreBorrowInst *sbi,
113+
SmallVectorImpl<Operand *> &newUses,
114+
DeadEndBlocks *deadEndBlocks,
115+
InstModCallbacks callbacks = InstModCallbacks());
116+
} // namespace swift
117+
118+
#endif

include/swift/SILOptimizer/Utils/GenericCloner.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ class GenericCloner
4141
RemappedScopeCache;
4242

4343
llvm::SmallVector<AllocStackInst *, 8> AllocStacks;
44+
llvm::SmallVector<StoreBorrowInst *, 8> StoreBorrowsToCleanup;
45+
llvm::SmallVector<TermInst *, 8> FunctionExits;
4446
AllocStackInst *ReturnValueAddr = nullptr;
4547

4648
public:
@@ -92,6 +94,11 @@ class GenericCloner
9294
if (Callback)
9395
Callback(Orig, Cloned);
9496

97+
if (auto *termInst = dyn_cast<TermInst>(Cloned)) {
98+
if (termInst->isFunctionExiting()) {
99+
FunctionExits.push_back(termInst);
100+
}
101+
}
95102
SILClonerWithScopes<GenericCloner>::postProcess(Orig, Cloned);
96103
}
97104

include/swift/SILOptimizer/Utils/InstOptUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ void emitDestroyOperation(SILBuilder &builder, SILLocation loc,
247247
/// Returns true, if there are no other users beside those collected in \p
248248
/// destroys, i.e. if \p inst can be considered as "dead".
249249
bool collectDestroys(SingleValueInstruction *inst,
250-
SmallVectorImpl<SILInstruction *> &destroys);
250+
SmallVectorImpl<Operand *> &destroys);
251251

252252
/// If Closure is a partial_apply or thin_to_thick_function with only local
253253
/// ref count users and a set of post-dominating releases:

include/swift/SILOptimizer/Utils/ValueLifetime.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,20 @@ class ValueLifetimeAnalysis {
138138
propagateLiveness();
139139
}
140140

141+
ValueLifetimeAnalysis(SILArgument *def, ArrayRef<Operand *> useRange)
142+
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
143+
for (auto *use : useRange)
144+
userSet.insert(use->getUser());
145+
propagateLiveness();
146+
}
147+
148+
ValueLifetimeAnalysis(SILInstruction *def, ArrayRef<Operand *> useRange)
149+
: defValue(def), inLiveBlocks(def->getFunction()), userSet() {
150+
for (auto *use : useRange)
151+
userSet.insert(use->getUser());
152+
propagateLiveness();
153+
}
154+
141155
/// Compute the LifetimeBoundary--the last users and boundary edges. This
142156
/// always succeeds.
143157
///

lib/SIL/Utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ target_sources(swiftSIL PRIVATE
1414
PrettyStackTrace.cpp
1515
Projection.cpp
1616
PrunedLiveness.cpp
17+
ScopedAddressUtils.cpp
1718
SILBridging.cpp
1819
SILInstructionWorklist.cpp
1920
SILRemarkStreamer.cpp

lib/SIL/Utils/MemAccessUtils.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,11 @@ bool AccessPathDefUseTraversal::visitUser(DFSEntry dfs) {
19351935
return true;
19361936
}
19371937
}
1938+
if (auto *sbi = dyn_cast<StoreBorrowInst>(use->getUser())) {
1939+
if (use->get() == sbi->getDest()) {
1940+
pushUsers(sbi, dfs);
1941+
}
1942+
}
19381943
if (isa<EndBorrowInst>(use->getUser())) {
19391944
return true;
19401945
}

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/SIL/Projection.h"
2121
#include "swift/SIL/PrunedLiveness.h"
2222
#include "swift/SIL/SILArgument.h"
23+
#include "swift/SIL/SILBuilder.h"
2324
#include "swift/SIL/SILInstruction.h"
2425

2526
using namespace swift;
@@ -917,7 +918,7 @@ swift::findTransitiveUsesForAddress(SILValue projectedAddress,
917918
isa<EndUnpairedAccessInst>(user) || isa<WitnessMethodInst>(user) ||
918919
isa<SwitchEnumAddrInst>(user) || isa<CheckedCastAddrBranchInst>(user) ||
919920
isa<SelectEnumAddrInst>(user) || isa<InjectEnumAddrInst>(user) ||
920-
isa<IsUniqueInst>(user)) {
921+
isa<IsUniqueInst>(user) || isa<ValueMetatypeInst>(user)) {
921922
leafUse(op);
922923
continue;
923924
}

0 commit comments

Comments
 (0)