Skip to content

Commit e571e2c

Browse files
authored
Merge pull request #7509 from gottesmm/more_borrow_propagation
More borrow stuff
2 parents 20d0441 + d4ae7a3 commit e571e2c

File tree

75 files changed

+1610
-772
lines changed

Some content is hidden

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

75 files changed

+1610
-772
lines changed

lib/SILGen/Cleanup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace Lowering {
3232
class JumpDest;
3333
class SILGenFunction;
3434
class ManagedValue;
35-
class BorrowedManagedValue;
35+
class SharedBorrowFormalEvaluation;
3636

3737
/// The valid states that a cleanup can be in.
3838
enum class CleanupState {
@@ -73,7 +73,7 @@ class LLVM_LIBRARY_VISIBILITY Cleanup {
7373
bool isActive() const { return state >= CleanupState::Active; }
7474
bool isDead() const { return state == CleanupState::Dead; }
7575

76-
virtual void emit(SILGenFunction &gen, CleanupLocation L) = 0;
76+
virtual void emit(SILGenFunction &gen, CleanupLocation loc) = 0;
7777
virtual void dump(SILGenFunction &gen) const = 0;
7878
};
7979

@@ -120,7 +120,7 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
120120
void setCleanupState(Cleanup &cleanup, CleanupState state);
121121

122122
friend class CleanupStateRestorationScope;
123-
friend class BorrowedManagedValue;
123+
friend class SharedBorrowFormalEvaluation;
124124

125125
public:
126126
CleanupManager(SILGenFunction &Gen)

lib/SILGen/FormalEvaluation.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ using namespace Lowering;
2323

2424
void FormalEvaluation::_anchor() {}
2525

26+
//===----------------------------------------------------------------------===//
27+
// Shared Borrow Formal Evaluation
28+
//===----------------------------------------------------------------------===//
29+
30+
void SharedBorrowFormalEvaluation::finish(SILGenFunction &gen) {
31+
gen.B.createEndBorrow(CleanupLocation::get(loc), borrowedValue,
32+
originalValue);
33+
}
34+
2635
//===----------------------------------------------------------------------===//
2736
// Formal Evaluation Scope
2837
//===----------------------------------------------------------------------===//

lib/SILGen/FormalEvaluation.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "Cleanup.h"
1717
#include "swift/Basic/DiverseStack.h"
18+
#include "swift/SIL/SILValue.h"
1819
#include "llvm/ADT/Optional.h"
1920

2021
namespace swift {
@@ -59,6 +60,21 @@ class FormalEvaluation {
5960
virtual void finish(SILGenFunction &gen) = 0;
6061
};
6162

63+
class SharedBorrowFormalEvaluation : public FormalEvaluation {
64+
SILValue originalValue;
65+
SILValue borrowedValue;
66+
67+
public:
68+
SharedBorrowFormalEvaluation(SILLocation loc, CleanupHandle cleanup,
69+
SILValue originalValue, SILValue borrowedValue)
70+
: FormalEvaluation(sizeof(*this), FormalEvaluation::Shared, loc, cleanup),
71+
originalValue(originalValue), borrowedValue(borrowedValue) {}
72+
void finish(SILGenFunction &gen) override;
73+
74+
SILValue getBorrowedValue() const { return borrowedValue; }
75+
SILValue getOriginalValue() const { return originalValue; }
76+
};
77+
6278
class FormalEvaluationContext {
6379
DiverseStack<FormalEvaluation, 128> stack;
6480

lib/SILGen/ManagedValue.cpp

Lines changed: 8 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -114,68 +114,12 @@ ManagedValue ManagedValue::borrow(SILGenFunction &gen, SILLocation loc) const {
114114
return gen.emitManagedBeginBorrow(loc, getValue());
115115
}
116116

117-
void BorrowedManagedValue::cleanupImpl() {
118-
if (!gen.B.hasValidInsertionPoint()) {
119-
handle.reset();
120-
return;
121-
}
122-
123-
// We had a trivial or an address value so there isn't anything to
124-
// cleanup. Still be sure to unset borrowedValue though.
125-
if (!handle.hasValue()) {
126-
borrowedValue = ManagedValue();
127-
return;
128-
}
129-
130-
assert(borrowedValue && "already cleaned up this object!?");
131-
132-
CleanupHandle handleValue = handle.getValue();
133-
CleanupLocation cleanupLoc = CleanupLocation::get(loc);
134-
135-
auto iter = gen.Cleanups.Stack.find(handleValue);
136-
assert(iter != gen.Cleanups.Stack.end() &&
137-
"can't change end of cleanups stack");
138-
139-
Cleanup &cleanup = *iter;
140-
assert(cleanup.isActive() && "Cleanup emitted out of order?!");
141-
142-
CleanupState newState =
143-
(cleanup.getState() == CleanupState::Active ? CleanupState::Dead
144-
: CleanupState::Dormant);
145-
cleanup.emit(gen, cleanupLoc);
146-
gen.Cleanups.setCleanupState(cleanup, newState);
147-
148-
borrowedValue = ManagedValue();
149-
handle.reset();
150-
}
151-
152-
BorrowedManagedValue::BorrowedManagedValue(SILGenFunction &gen,
153-
ManagedValue originalValue,
154-
SILLocation loc)
155-
: gen(gen), borrowedValue(), handle(), loc(loc) {
156-
if (!originalValue)
157-
return;
158-
auto &lowering = gen.F.getTypeLowering(originalValue.getType());
159-
assert(lowering.getLoweredType().getObjectType() ==
160-
originalValue.getType().getObjectType());
161-
162-
if (lowering.isTrivial()) {
163-
borrowedValue = ManagedValue::forUnmanaged(originalValue.getValue());
164-
return;
165-
}
166-
167-
if (originalValue.getOwnershipKind() == ValueOwnershipKind::Guaranteed) {
168-
borrowedValue = ManagedValue::forUnmanaged(originalValue.getValue());
169-
return;
170-
}
171-
172-
if (originalValue.getType().isAddress()) {
173-
borrowedValue = ManagedValue::forUnmanaged(originalValue.getValue());
174-
return;
175-
}
176-
177-
SILValue borrowed = gen.B.createBeginBorrow(loc, originalValue.getValue());
178-
if (borrowed->getType().isObject())
179-
handle = gen.enterEndBorrowCleanup(originalValue.getValue(), borrowed);
180-
borrowedValue = ManagedValue(borrowed, CleanupHandle::invalid());
117+
ManagedValue ManagedValue::formalEvaluationBorrow(SILGenFunction &gen,
118+
SILLocation loc) const {
119+
assert(getValue() && "cannot borrow an invalid or in-context value");
120+
if (isLValue())
121+
return *this;
122+
if (getType().isAddress())
123+
return ManagedValue::forUnmanaged(getValue());
124+
return gen.emitFormalEvaluationManagedBeginBorrow(loc, getValue());
181125
}

lib/SILGen/ManagedValue.h

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ class ManagedValue {
257257
/// will not be forwarded until the borrowed value is fully used.
258258
ManagedValue borrow(SILGenFunction &gen, SILLocation loc) const;
259259

260+
/// Return a formally evaluated "borrowed" version of this value.
261+
ManagedValue formalEvaluationBorrow(SILGenFunction &gen,
262+
SILLocation loc) const;
263+
260264
ManagedValue unmanagedBorrow() const {
261265
return isLValue() ? *this : ManagedValue::forUnmanaged(getValue());
262266
}
@@ -362,36 +366,6 @@ class ConsumableManagedValue {
362366
}
363367
};
364368

365-
/// An RAII object that allows a user to borrow a value without a specific scope
366-
/// that ensures that the object is cleaned up before other scoped cleanups
367-
/// occur. The way cleanup is triggered is by calling:
368-
///
369-
/// std::move(value).cleanup();
370-
class BorrowedManagedValue {
371-
SILGenFunction &gen;
372-
ManagedValue borrowedValue;
373-
Optional<CleanupHandle> handle;
374-
SILLocation loc;
375-
376-
public:
377-
BorrowedManagedValue(SILGenFunction &gen, ManagedValue originalValue,
378-
SILLocation loc);
379-
~BorrowedManagedValue() {
380-
assert(!borrowedValue &&
381-
"Did not manually cleanup borrowed managed value?!");
382-
}
383-
BorrowedManagedValue(const BorrowedManagedValue &) = delete;
384-
BorrowedManagedValue(BorrowedManagedValue &&) = delete;
385-
BorrowedManagedValue &operator=(const BorrowedManagedValue &) = delete;
386-
BorrowedManagedValue &operator=(BorrowedManagedValue &&) = delete;
387-
388-
void cleanup() && { cleanupImpl(); }
389-
operator ManagedValue() const { return borrowedValue; }
390-
391-
private:
392-
void cleanupImpl();
393-
};
394-
395369
} // namespace Lowering
396370
} // namespace swift
397371

lib/SILGen/SILGenDecl.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1210,12 +1210,6 @@ CleanupHandle SILGenFunction::enterDestroyCleanup(SILValue valueOrAddr) {
12101210
return Cleanups.getTopCleanup();
12111211
}
12121212

1213-
CleanupHandle SILGenFunction::enterEndBorrowCleanup(SILValue original,
1214-
SILValue borrowed) {
1215-
Cleanups.pushCleanup<EndBorrowCleanup>(original, borrowed);
1216-
return Cleanups.getTopCleanup();
1217-
}
1218-
12191213
namespace {
12201214
/// A cleanup that deinitializes an opaque existential container
12211215
/// before a value has been stored into it, or after its value was taken.

lib/SILGen/SILGenExpr.cpp

Lines changed: 116 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,116 @@ SILGenFunction::emitManagedBeginBorrow(SILLocation loc, SILValue v,
137137
return emitManagedBorrowedRValueWithCleanup(v, bbi, lowering);
138138
}
139139

140+
namespace {
141+
142+
struct EndBorrowCleanup : Cleanup {
143+
SILValue originalValue;
144+
SILValue borrowedValue;
145+
146+
EndBorrowCleanup(SILValue originalValue, SILValue borrowedValue)
147+
: originalValue(originalValue), borrowedValue(borrowedValue) {}
148+
149+
void emit(SILGenFunction &gen, CleanupLocation l) override {
150+
gen.B.createEndBorrow(l, borrowedValue, originalValue);
151+
}
152+
153+
void dump(SILGenFunction &gen) const override {
154+
#ifndef NDEBUG
155+
llvm::errs() << "EndBorrowCleanup "
156+
<< "State:" << getState() << "\n"
157+
<< "original:" << originalValue << "\n"
158+
<< "borrowed:" << borrowedValue << "\n";
159+
#endif
160+
}
161+
};
162+
163+
struct FormalEvaluationEndBorrowCleanup : Cleanup {
164+
FormalEvaluationContext::stable_iterator Depth;
165+
166+
FormalEvaluationEndBorrowCleanup() : Depth() {}
167+
168+
void emit(SILGenFunction &gen, CleanupLocation l) override {
169+
getEvaluation(gen).finish(gen);
170+
}
171+
172+
void dump(SILGenFunction &gen) const override {
173+
#ifndef NDEBUG
174+
llvm::errs() << "FormalEvaluationEndBorrowCleanup "
175+
<< "State:" << getState() << "\n"
176+
<< "original:" << getOriginalValue(gen) << "\n"
177+
<< "borrowed:" << getBorrowedValue(gen) << "\n";
178+
#endif
179+
}
180+
181+
SharedBorrowFormalEvaluation &getEvaluation(SILGenFunction &gen) const {
182+
auto &evaluation = *gen.FormalEvalContext.find(Depth);
183+
assert(evaluation.getKind() == FormalEvaluation::Shared);
184+
return static_cast<SharedBorrowFormalEvaluation &>(evaluation);
185+
}
186+
187+
SILValue getOriginalValue(SILGenFunction &gen) const {
188+
return getEvaluation(gen).getOriginalValue();
189+
}
190+
191+
SILValue getBorrowedValue(SILGenFunction &gen) const {
192+
return getEvaluation(gen).getBorrowedValue();
193+
}
194+
};
195+
196+
} // end anonymous namespace
197+
198+
ManagedValue
199+
SILGenFunction::emitFormalEvaluationManagedBeginBorrow(SILLocation loc,
200+
SILValue v) {
201+
if (v.getOwnershipKind() == ValueOwnershipKind::Guaranteed)
202+
return ManagedValue::forUnmanaged(v);
203+
auto &lowering = F.getTypeLowering(v->getType());
204+
return emitFormalEvaluationManagedBeginBorrow(loc, v, lowering);
205+
}
206+
207+
ManagedValue SILGenFunction::emitFormalEvaluationManagedBeginBorrow(
208+
SILLocation loc, SILValue v, const TypeLowering &lowering) {
209+
assert(lowering.getLoweredType().getObjectType() ==
210+
v->getType().getObjectType());
211+
if (lowering.isTrivial())
212+
return ManagedValue::forUnmanaged(v);
213+
if (v.getOwnershipKind() == ValueOwnershipKind::Guaranteed)
214+
return ManagedValue::forUnmanaged(v);
215+
auto *bbi = B.createBeginBorrow(loc, v);
216+
return emitFormalEvaluationManagedBorrowedRValueWithCleanup(loc, v, bbi,
217+
lowering);
218+
}
219+
220+
ManagedValue
221+
SILGenFunction::emitFormalEvaluationManagedBorrowedRValueWithCleanup(
222+
SILLocation loc, SILValue original, SILValue borrowed) {
223+
auto &lowering = F.getTypeLowering(original->getType());
224+
return emitFormalEvaluationManagedBorrowedRValueWithCleanup(
225+
loc, original, borrowed, lowering);
226+
}
227+
228+
ManagedValue
229+
SILGenFunction::emitFormalEvaluationManagedBorrowedRValueWithCleanup(
230+
SILLocation loc, SILValue original, SILValue borrowed,
231+
const TypeLowering &lowering) {
232+
assert(lowering.getLoweredType().getObjectType() ==
233+
original->getType().getObjectType());
234+
if (lowering.isTrivial())
235+
return ManagedValue::forUnmanaged(borrowed);
236+
237+
if (!borrowed->getType().isObject()) {
238+
return ManagedValue(borrowed, CleanupHandle::invalid());
239+
}
240+
241+
assert(InWritebackScope && "Must be in formal evaluation scope");
242+
Cleanups.pushCleanup<FormalEvaluationEndBorrowCleanup>();
243+
CleanupHandle handle = Cleanups.getTopCleanup();
244+
FormalEvalContext.push<SharedBorrowFormalEvaluation>(loc, handle, original,
245+
borrowed);
246+
247+
return ManagedValue(borrowed, CleanupHandle::invalid());
248+
}
249+
140250
ManagedValue
141251
SILGenFunction::emitManagedBorrowedRValueWithCleanup(SILValue original,
142252
SILValue borrowed) {
@@ -153,8 +263,9 @@ ManagedValue SILGenFunction::emitManagedBorrowedRValueWithCleanup(
153263
if (lowering.isTrivial())
154264
return ManagedValue::forUnmanaged(borrowed);
155265

156-
if (borrowed->getType().isObject())
157-
enterEndBorrowCleanup(original, borrowed);
266+
if (borrowed->getType().isObject()) {
267+
Cleanups.pushCleanup<EndBorrowCleanup>(original, borrowed);
268+
}
158269
return ManagedValue(borrowed, CleanupHandle::invalid());
159270
}
160271

@@ -394,7 +505,7 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
394505
AccessSemantics semantics, SGFContext C) {
395506
assert(!ncRefType->is<LValueType>() &&
396507
"RValueEmitter shouldn't be called on lvalues");
397-
508+
398509
// Any writebacks for this access are tightly scoped.
399510
FormalEvaluationScope scope(*this);
400511

@@ -494,7 +605,8 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
494605
refType, emitManagedRValueWithCleanup(Scalar));
495606
}
496607

497-
auto Result = ManagedValue::forUnmanaged(Scalar);
608+
// This is a let, so we can make guarantees, so begin the borrow scope.
609+
ManagedValue Result = emitManagedBeginBorrow(loc, Scalar);
498610

499611
// If the client can't handle a +0 result, retain it to get a +1.
500612
// This is a 'let', so we can make guarantees.

lib/SILGen/SILGenFunction.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,18 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
11061106
ManagedValue emitManagedBorrowedRValueWithCleanup(
11071107
SILValue original, SILValue borrowedValue, const TypeLowering &lowering);
11081108

1109+
ManagedValue emitFormalEvaluationManagedBorrowedRValueWithCleanup(
1110+
SILLocation loc, SILValue original, SILValue borrowedValue);
1111+
ManagedValue emitFormalEvaluationManagedBorrowedRValueWithCleanup(
1112+
SILLocation loc, SILValue original, SILValue borrowedValue,
1113+
const TypeLowering &lowering);
1114+
1115+
ManagedValue emitFormalEvaluationManagedBeginBorrow(SILLocation loc,
1116+
SILValue v);
1117+
ManagedValue
1118+
emitFormalEvaluationManagedBeginBorrow(SILLocation loc, SILValue v,
1119+
const TypeLowering &lowering);
1120+
11091121
ManagedValue emitManagedRValueWithCleanup(SILValue v);
11101122
ManagedValue emitManagedRValueWithCleanup(SILValue v,
11111123
const TypeLowering &lowering);
@@ -1550,11 +1562,6 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
15501562
CanType concreteFormalType,
15511563
ExistentialRepresentation repr);
15521564

1553-
/// Enter a cleanup to emit an EndBorrow stating that \p borrowed (the
1554-
/// borrowed entity) is no longer borrowed from \p original, the original
1555-
/// value.
1556-
CleanupHandle enterEndBorrowCleanup(SILValue original, SILValue borrowed);
1557-
15581565
/// Evaluate an Expr as an lvalue.
15591566
LValue emitLValue(Expr *E, AccessKind accessKind);
15601567

0 commit comments

Comments
 (0)