Skip to content

Commit cd06759

Browse files
authored
Merge pull request #65835 from meg-gupta/newflags
Add new flags "reborrow" and "escaping" to SILArgument.
2 parents 72df1fc + 1dc713e commit cd06759

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)