Skip to content

Commit 1dc713e

Browse files
committed
Add new flags "reborrow" and "escaping" to SILArgument.
"reborrow" flag on the SILArgument avoids transitive walk over the phi operandsi to determine if it is a reborrow in multiple utilities. SIL transforms must keep the flag up-to-date by calling SILArgument::setReborrow. SILVerifier checks to ensure the flag is not invalidated. Currently "escaping" is not used anywhere.
1 parent 8ab43a4 commit 1dc713e

Some content is hidden

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

42 files changed

+436
-158
lines changed

include/swift/SIL/OwnershipUseVisitor.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -317,14 +317,11 @@ bool OwnershipUseVisitor<Impl>::visitInteriorUses(SILValue ssaDef) {
317317
// Inner adjacent reborrows are considered inner borrow scopes.
318318
if (auto phi = SILArgument::asPhi(ssaDef)) {
319319
if (!visitInnerAdjacentPhis(phi, [&](SILArgument *innerPhi) {
320-
// TODO: Remove this call to isGuaranteedForwarding.
321-
// The phi itself should know if it is a reborrow.
322-
if (isGuaranteedForwarding(innerPhi)) {
323-
return visitGuaranteedUses(innerPhi);
324-
} else {
325-
return visitInnerAdjacentReborrow(innerPhi);
326-
}
327-
})) {
320+
if (innerPhi->isGuaranteedForwarding()) {
321+
return visitGuaranteedUses(innerPhi);
322+
}
323+
return visitInnerAdjacentReborrow(innerPhi);
324+
})) {
328325
return false;
329326
}
330327
}

include/swift/SIL/OwnershipUtils.h

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -57,45 +57,13 @@ bool canOpcodeForwardInnerGuaranteedValues(SILValue value);
5757
/// the operation may be trivially rewritten with Guaranteed ownership.
5858
bool canOpcodeForwardInnerGuaranteedValues(Operand *use);
5959

60+
bool computeIsScoped(SILArgument *arg);
61+
62+
bool computeIsReborrow(SILArgument *arg);
63+
6064
// This is the use-def equivalent of use->getOperandOwnership() ==
6165
// OperandOwnership::GuaranteedForwarding.
62-
inline bool isGuaranteedForwarding(SILValue value) {
63-
if (value->getOwnershipKind() != OwnershipKind::Guaranteed) {
64-
return false;
65-
}
66-
// NOTE: canOpcodeForwardInnerGuaranteedValues returns true for transformation
67-
// terminator results.
68-
if (canOpcodeForwardInnerGuaranteedValues(value) ||
69-
isa<SILFunctionArgument>(value)) {
70-
return true;
71-
}
72-
// If not a phi, return false
73-
auto *phi = dyn_cast<SILPhiArgument>(value);
74-
if (!phi || !phi->isPhi()) {
75-
return false;
76-
}
77-
// For a phi, if we find GuaranteedForwarding phi operand on any incoming
78-
// path, we return true. Additional verification is added to ensure
79-
// GuaranteedForwarding phi operands are found on zero or all paths in the
80-
// OwnershipVerifier.
81-
bool isGuaranteedForwardingPhi = false;
82-
phi->visitTransitiveIncomingPhiOperands([&](auto *, auto *op) -> bool {
83-
auto opValue = op->get();
84-
assert(opValue->getOwnershipKind().isCompatibleWith(
85-
OwnershipKind::Guaranteed));
86-
if (canOpcodeForwardInnerGuaranteedValues(opValue) ||
87-
isa<SILFunctionArgument>(opValue)) {
88-
isGuaranteedForwardingPhi = true;
89-
return false;
90-
}
91-
auto *phi = dyn_cast<SILPhiArgument>(opValue);
92-
if (!phi || !phi->isPhi()) {
93-
return false;
94-
}
95-
return true;
96-
});
97-
return isGuaranteedForwardingPhi;
98-
}
66+
bool computeIsGuaranteedForwarding(SILValue value);
9967

10068
/// Is the opcode that produces \p value capable of forwarding owned values?
10169
///
@@ -523,7 +491,7 @@ class BorrowedValueKind {
523491
})) {
524492
return Kind::Invalid;
525493
}
526-
if (isGuaranteedForwarding(value)) {
494+
if (cast<SILArgument>(value)->isGuaranteedForwarding()) {
527495
return Kind::Invalid;
528496
}
529497
return Kind::Phi;

include/swift/SIL/SILArgument.h

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,21 @@ class SILArgument : public ValueBase {
7575
protected:
7676
SILArgument(ValueKind subClassKind, SILBasicBlock *inputParentBlock,
7777
SILType type, ValueOwnershipKind ownershipKind,
78-
const ValueDecl *inputDecl = nullptr);
78+
const ValueDecl *inputDecl = nullptr, bool reborrow = false,
79+
bool escaping = false);
7980

8081
// A special constructor, only intended for use in
8182
// SILBasicBlock::replacePHIArg and replaceFunctionArg.
8283
explicit SILArgument(ValueKind subClassKind, SILType type,
8384
ValueOwnershipKind ownershipKind,
84-
const ValueDecl *inputDecl = nullptr)
85-
: ValueBase(subClassKind, type),
86-
parentBlock(nullptr), decl(inputDecl) {
85+
const ValueDecl *inputDecl = nullptr,
86+
bool reborrow = false, bool escaping = false)
87+
: ValueBase(subClassKind, type), parentBlock(nullptr), decl(inputDecl) {
8788
sharedUInt8().SILArgument.valueOwnershipKind = uint8_t(ownershipKind);
89+
// When the optimizer creates reborrows, reborrow flag needs to be set by
90+
// calling setReborrow.
91+
sharedUInt8().SILArgument.reborrow = false;
92+
sharedUInt8().SILArgument.escaping = false;
8893
}
8994

9095
public:
@@ -95,10 +100,41 @@ class SILArgument : public ValueBase {
95100
return ValueOwnershipKind(sharedUInt8().SILArgument.valueOwnershipKind);
96101
}
97102

103+
bool isScoped() const {
104+
auto ownershipKind = getOwnershipKind();
105+
if (ownershipKind == OwnershipKind::Owned) {
106+
return true;
107+
}
108+
if (ownershipKind != OwnershipKind::Guaranteed) {
109+
return false;
110+
}
111+
return isReborrow();
112+
}
113+
114+
bool isReborrow() const {
115+
return ValueOwnershipKind(sharedUInt8().SILArgument.reborrow);
116+
}
117+
118+
bool isGuaranteedForwarding() const {
119+
return getOwnershipKind() == OwnershipKind::Guaranteed && !isReborrow();
120+
}
121+
122+
bool isEscaping() const {
123+
return ValueOwnershipKind(sharedUInt8().SILArgument.escaping);
124+
}
125+
98126
void setOwnershipKind(ValueOwnershipKind newKind) {
99127
sharedUInt8().SILArgument.valueOwnershipKind = uint8_t(newKind);
100128
}
101129

130+
void setReborrow(bool isReborrow) {
131+
sharedUInt8().SILArgument.reborrow = isReborrow;
132+
}
133+
134+
void setEscaping(bool isEscaping) {
135+
sharedUInt8().SILArgument.escaping = isEscaping;
136+
}
137+
102138
SILBasicBlock *getParent() const { return parentBlock; }
103139

104140
/// Returns true if this argument is erased from a basic block.
@@ -223,14 +259,18 @@ class SILPhiArgument : public SILArgument {
223259

224260
SILPhiArgument(SILBasicBlock *parentBlock, SILType type,
225261
ValueOwnershipKind ownershipKind,
226-
const ValueDecl *decl = nullptr)
262+
const ValueDecl *decl = nullptr, bool isReborrow = false,
263+
bool isEscaping = false)
227264
: SILArgument(ValueKind::SILPhiArgument, parentBlock, type, ownershipKind,
228-
decl) {}
265+
decl, isReborrow, isEscaping) {}
266+
229267
// A special constructor, only intended for use in
230268
// SILBasicBlock::replacePHIArg.
231269
explicit SILPhiArgument(SILType type, ValueOwnershipKind ownershipKind,
232-
const ValueDecl *decl = nullptr)
233-
: SILArgument(ValueKind::SILPhiArgument, type, ownershipKind, decl) {}
270+
const ValueDecl *decl = nullptr,
271+
bool isReborrow = false, bool isEscaping = false)
272+
: SILArgument(ValueKind::SILPhiArgument, type, ownershipKind, decl,
273+
isReborrow, isEscaping) {}
234274

235275
public:
236276
/// Return true if this is block argument is a phi, as opposed to a terminator

include/swift/SIL/SILBasicBlock.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -350,24 +350,31 @@ public SwiftObjectHeader {
350350
/// replacePhiArgumentAndRAUW.
351351
SILPhiArgument *replacePhiArgument(unsigned i, SILType type,
352352
ValueOwnershipKind kind,
353-
const ValueDecl *decl = nullptr);
353+
const ValueDecl *decl = nullptr,
354+
bool isReborrow = false,
355+
bool isEscaping = false);
354356

355357
/// Replace phi argument \p i and RAUW all uses.
356-
SILPhiArgument *
357-
replacePhiArgumentAndReplaceAllUses(unsigned i, SILType type,
358-
ValueOwnershipKind kind,
359-
const ValueDecl *decl = nullptr);
358+
SILPhiArgument *replacePhiArgumentAndReplaceAllUses(
359+
unsigned i, SILType type, ValueOwnershipKind kind,
360+
const ValueDecl *decl = nullptr, bool isReborrow = false,
361+
bool isEscaping = false);
360362

361363
/// Allocate a new argument of type \p Ty and append it to the argument
362-
/// list. Optionally you can pass in a value decl parameter.
364+
/// list. Optionally you can pass in a value decl parameter, reborrow flag and
365+
/// escaping flag.
363366
SILPhiArgument *createPhiArgument(SILType Ty, ValueOwnershipKind Kind,
364-
const ValueDecl *D = nullptr);
367+
const ValueDecl *D = nullptr,
368+
bool isReborrow = false,
369+
bool isEscaping = false);
365370

366371
/// Insert a new SILPhiArgument with type \p Ty and \p Decl at position \p
367372
/// AtArgPos.
368373
SILPhiArgument *insertPhiArgument(unsigned AtArgPos, SILType Ty,
369374
ValueOwnershipKind Kind,
370-
const ValueDecl *D = nullptr);
375+
const ValueDecl *D = nullptr,
376+
bool isReborrow = false,
377+
bool isEscaping = false);
371378

372379
/// Remove all block arguments.
373380
void dropAllArguments();

include/swift/SIL/SILCloner.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -734,7 +734,8 @@ void SILCloner<ImplClass>::clonePhiArgs(SILBasicBlock *oldBB) {
734734
// Create new arguments for each of the original block's arguments.
735735
for (auto *Arg : oldBB->getSILPhiArguments()) {
736736
SILValue mappedArg = mappedBB->createPhiArgument(
737-
getOpType(Arg->getType()), Arg->getOwnershipKind());
737+
getOpType(Arg->getType()), Arg->getOwnershipKind(), Arg->getDecl(),
738+
Arg->isReborrow(), Arg->isEscaping());
738739

739740
asImpl().mapValue(Arg, mappedArg);
740741
}

include/swift/SIL/SILNode.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,6 @@ class alignas(8) SILNode :
181181
SHARED_TEMPLATE_FIELD(typename, SwitchEnumInstBase, bool hasDefault);
182182
SHARED_TEMPLATE_FIELD(SILInstructionKind, LoadReferenceInstBase, bool isTake);
183183
SHARED_TEMPLATE_FIELD(SILInstructionKind, StoreReferenceInstBase, bool isInitializationOfDest);
184-
SHARED_FIELD(SILArgument, uint8_t valueOwnershipKind);
185184
SHARED_FIELD(MultipleValueInstructionResult, uint8_t valueOwnershipKind);
186185
SHARED_FIELD(UncheckedOwnershipConversionInst, uint8_t valueOwnershipKind);
187186
SHARED_FIELD(StoreInst, uint8_t ownershipQualifier);
@@ -203,6 +202,11 @@ class alignas(8) SILNode :
203202
SHARED_FIELD(ConvertFunctionInst, bool withoutActuallyEscaping);
204203
SHARED_FIELD(BeginCOWMutationInst, bool native);
205204

205+
SHARED_FIELD(SILArgument, uint8_t
206+
valueOwnershipKind : NumVOKindBits,
207+
reborrow : 1,
208+
escaping : 1);
209+
206210
SHARED_FIELD(DebugValueInst, uint8_t
207211
poisonRefs : 1,
208212
usesMoveableValueDebugInfo : 1,

include/swift/SIL/SILValue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,8 @@ class ValueBase : public SILNode, public SILAllocated<ValueBase> {
570570

571571
bool isLexical() const;
572572

573+
bool isGuaranteedForwarding() const;
574+
573575
/// Unsafely eliminate moveonly from this value's type. Returns true if the
574576
/// value's underlying type was move only and thus was changed. Returns false
575577
/// otherwise.

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -435,11 +435,11 @@ OperandOwnershipClassifier::visitSelectEnumInst(SelectEnumInst *i) {
435435
}
436436

437437
OperandOwnership OperandOwnershipClassifier::visitBranchInst(BranchInst *bi) {
438-
ValueOwnershipKind destBlockArgOwnershipKind =
439-
bi->getDestBB()->getArgument(getOperandIndex())->getOwnershipKind();
438+
auto *destArg = bi->getDestBB()->getArgument(getOperandIndex());
439+
ValueOwnershipKind destBlockArgOwnershipKind = destArg->getOwnershipKind();
440440

441441
if (destBlockArgOwnershipKind == OwnershipKind::Guaranteed) {
442-
return isGuaranteedForwarding(getValue())
442+
return destArg->isGuaranteedForwarding()
443443
? OperandOwnership::GuaranteedForwarding
444444
: OperandOwnership::Reborrow;
445445
}

lib/SIL/IR/SILArgument.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,13 @@ using namespace swift;
2727
SILArgument::SILArgument(ValueKind subClassKind,
2828
SILBasicBlock *inputParentBlock, SILType type,
2929
ValueOwnershipKind ownershipKind,
30-
const ValueDecl *inputDecl)
31-
: ValueBase(subClassKind, type),
32-
parentBlock(inputParentBlock), decl(inputDecl) {
30+
const ValueDecl *inputDecl, bool reborrow,
31+
bool escaping)
32+
: ValueBase(subClassKind, type), parentBlock(inputParentBlock),
33+
decl(inputDecl) {
3334
sharedUInt8().SILArgument.valueOwnershipKind = uint8_t(ownershipKind);
35+
sharedUInt8().SILArgument.reborrow = reborrow;
36+
sharedUInt8().SILArgument.escaping = escaping;
3437
inputParentBlock->insertArgument(inputParentBlock->args_end(), this);
3538
}
3639

lib/SIL/IR/SILBasicBlock.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,9 @@ SILFunctionArgument *SILBasicBlock::replaceFunctionArgument(
203203
/// ValueDecl D).
204204
SILPhiArgument *SILBasicBlock::replacePhiArgument(unsigned i, SILType Ty,
205205
ValueOwnershipKind Kind,
206-
const ValueDecl *D) {
206+
const ValueDecl *D,
207+
bool isReborrow,
208+
bool isEscaping) {
207209
assert(!isEntry() && "PHI Arguments can not be in the entry block");
208210
SILFunction *F = getParent();
209211
SILModule &M = F->getModule();
@@ -212,7 +214,8 @@ SILPhiArgument *SILBasicBlock::replacePhiArgument(unsigned i, SILType Ty,
212214

213215
assert(ArgumentList[i]->use_empty() && "Expected no uses of the old BB arg!");
214216

215-
SILPhiArgument *NewArg = new (M) SILPhiArgument(Ty, Kind, D);
217+
SILPhiArgument *NewArg =
218+
new (M) SILPhiArgument(Ty, Kind, D, isReborrow, isEscaping);
216219
NewArg->setParent(this);
217220
ArgumentList[i]->parentBlock = nullptr;
218221

@@ -224,7 +227,8 @@ SILPhiArgument *SILBasicBlock::replacePhiArgument(unsigned i, SILType Ty,
224227
}
225228

226229
SILPhiArgument *SILBasicBlock::replacePhiArgumentAndReplaceAllUses(
227-
unsigned i, SILType ty, ValueOwnershipKind kind, const ValueDecl *d) {
230+
unsigned i, SILType ty, ValueOwnershipKind kind, const ValueDecl *d,
231+
bool isReborrow, bool isEscaping) {
228232
// Put in an undef placeholder before we do the replacement since
229233
// replacePhiArgument() expects the replaced argument to not have
230234
// any uses.
@@ -238,7 +242,7 @@ SILPhiArgument *SILBasicBlock::replacePhiArgumentAndReplaceAllUses(
238242
}
239243

240244
// Perform the replacement.
241-
auto *newArg = replacePhiArgument(i, ty, kind, d);
245+
auto *newArg = replacePhiArgument(i, ty, kind, d, isReborrow, isEscaping);
242246

243247
// Wire back up the uses.
244248
while (!operands.empty()) {
@@ -250,20 +254,26 @@ SILPhiArgument *SILBasicBlock::replacePhiArgumentAndReplaceAllUses(
250254

251255
SILPhiArgument *SILBasicBlock::createPhiArgument(SILType Ty,
252256
ValueOwnershipKind Kind,
253-
const ValueDecl *D) {
257+
const ValueDecl *D,
258+
bool isReborrow,
259+
bool isEscaping) {
254260
assert(!isEntry() && "PHI Arguments can not be in the entry block");
255261
if (Ty.isTrivial(*getParent()))
256262
Kind = OwnershipKind::None;
257-
return new (getModule()) SILPhiArgument(this, Ty, Kind, D);
263+
return new (getModule())
264+
SILPhiArgument(this, Ty, Kind, D, isReborrow, isEscaping);
258265
}
259266

260267
SILPhiArgument *SILBasicBlock::insertPhiArgument(unsigned AtArgPos, SILType Ty,
261268
ValueOwnershipKind Kind,
262-
const ValueDecl *D) {
269+
const ValueDecl *D,
270+
bool isReborrow,
271+
bool isEscaping) {
263272
assert(!isEntry() && "PHI Arguments can not be in the entry block");
264273
if (Ty.isTrivial(*getParent()))
265274
Kind = OwnershipKind::None;
266-
auto *arg = new (getModule()) SILPhiArgument(Ty, Kind, D);
275+
auto *arg =
276+
new (getModule()) SILPhiArgument(Ty, Kind, D, isReborrow, isEscaping);
267277
arg->parentBlock = this;
268278
insertArgument(ArgumentList.begin() + AtArgPos, arg);
269279
return arg;

0 commit comments

Comments
 (0)