Skip to content

Commit c35ff33

Browse files
committed
[ownership] Add a subclass for all OwnershipForwarding instructions and fix the classof to the various ownership abstract classes so isa/dyn_cast work.
I think what was happening here was that we were using one of the superclass classofs and were getting lucky since in the place I was using this I was guaranteed to have single value instructions and that is what I wrote as my first case X ). I also added more robust checks tieing the older isGuaranteed...* APIs to the ForwardingOperand API. I also eliminated the notion of Branch being an owned forwarding instruction. We only used this in one place in the compiler (when finding owned value introducers), yet we treat a phi as an introducer, so we would never hit a branch in our search since we would stop at the phi argument. The bigger picture here is that this means that all "forwarding instructions" either forward ownership for everything or for everything but owned/unowned. And for those listening in, I did find one instruction that was from an ownership forwarding subclass but was not marked as forwarding: DifferentiableFunctionInst. With this change, we can no longer by mistake have such errors enter the code base.
1 parent 5ea3bb2 commit c35ff33

File tree

9 files changed

+229
-114
lines changed

9 files changed

+229
-114
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,13 @@ bool isValueAddressOrTrivial(SILValue v);
3535
/// These operations forward both owned and guaranteed ownership.
3636
bool isOwnershipForwardingValueKind(SILNodeKind kind);
3737

38-
/// Is this an instruction that can forward both owned and guaranteed ownership
38+
/// Is this an operand that can forward both owned and guaranteed ownership
3939
/// kinds.
40-
bool isOwnershipForwardingInst(SILInstruction *i);
40+
bool isOwnershipForwardingUse(Operand *op);
4141

42-
/// Is this an instruction that can forward guaranteed ownership.
43-
bool isGuaranteedForwardingInst(SILInstruction *i);
42+
/// Is this an operand that forwards guaranteed ownership from its value to a
43+
/// result of the using instruction.
44+
bool isGuaranteedForwardingUse(Operand *op);
4445

4546
/// These operations forward guaranteed ownership, but don't necessarily forward
4647
/// owned values.
@@ -54,12 +55,12 @@ bool isGuaranteedForwardingValue(SILValue value);
5455
/// forward guaranteed ownership.
5556
bool isOwnedForwardingValueKind(SILNodeKind kind);
5657

57-
/// Does this SILInstruction 'forward' owned ownership, but may not be able to
58-
/// forward guaranteed ownership.
59-
bool isOwnedForwardingInstruction(SILInstruction *inst);
60-
61-
/// Does this value 'forward' owned ownership, but may not be able to forward
58+
/// Does this operand 'forward' owned ownership, but may not be able to forward
6259
/// guaranteed ownership.
60+
bool isOwnedForwardingUse(Operand *use);
61+
62+
/// Is this value the result of an instruction that 'forward's owned ownership,
63+
/// but may not be able to forward guaranteed ownership.
6364
///
6465
/// This will be either a multiple value instruction resuilt, a single value
6566
/// instruction that forwards or an argument that forwards the ownership from a
@@ -78,6 +79,10 @@ class ForwardingOperand {
7879
void setOwnershipKind(ValueOwnershipKind newKind) const;
7980
void replaceOwnershipKind(ValueOwnershipKind oldKind,
8081
ValueOwnershipKind newKind) const;
82+
83+
OwnershipForwardingInst *getUser() const {
84+
return cast<OwnershipForwardingInst>(use->getUser());
85+
}
8186
};
8287

8388
/// Returns true if the instruction is a 'reborrow'.

include/swift/SIL/SILInstruction.h

Lines changed: 181 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -856,38 +856,95 @@ inline SingleValueInstruction *SILNode::castToSingleValueInstruction() {
856856
}
857857
}
858858

859-
#define DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(ID) \
860-
static bool classof(const SILNode *node) { \
861-
return node->getKind() >= SILNodeKind::First_##ID && \
862-
node->getKind() <= SILNodeKind::Last_##ID; \
863-
} \
864-
static bool classof(const SingleValueInstruction *inst) { \
865-
return inst->getKind() >= SILInstructionKind::First_##ID && \
866-
inst->getKind() <= SILInstructionKind::Last_##ID; \
859+
#define DEFINE_ABSTRACT_SINGLE_VALUE_INST_BOILERPLATE(ID) \
860+
static bool classof(const SILNode *node) { \
861+
return node->getKind() >= SILNodeKind::First_##ID && \
862+
node->getKind() <= SILNodeKind::Last_##ID; \
863+
} \
864+
static bool classof(const SingleValueInstruction *inst) { \
865+
return inst->getKind() >= SILInstructionKind::First_##ID && \
866+
inst->getKind() <= SILInstructionKind::Last_##ID; \
867+
}
868+
869+
/// Abstract base class used for isa checks on instructions to determine if they
870+
/// forward ownership and to verify that the set of ownership instructions and
871+
/// the ownership utilities stay in sync via assertions.
872+
///
873+
/// NOTE: We assume that the constructor for the instruction subclass that
874+
/// initializes the kind field on our object is run before our constructor runs.
875+
class OwnershipForwardingInst {
876+
ValueOwnershipKind ownershipKind;
877+
878+
protected:
879+
OwnershipForwardingInst(SILInstructionKind kind,
880+
ValueOwnershipKind ownershipKind)
881+
: ownershipKind(ownershipKind) {
882+
assert(classof(kind) && "Invalid subclass?!");
883+
}
884+
885+
public:
886+
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
887+
888+
void setOwnershipKind(ValueOwnershipKind newKind) { ownershipKind = newKind; }
889+
890+
static bool classof(const SILNode *node) {
891+
if (auto *i = dyn_cast<SILInstruction>(node))
892+
return classof(i);
893+
return false;
867894
}
868895

896+
// Defined inline below due to forward declaration issues.
897+
static bool classof(const SILInstruction *inst);
898+
899+
/// Define inline below due to forward declaration issues.
900+
static bool classof(SILInstructionKind kind);
901+
};
902+
869903
/// A single value inst that forwards a static ownership from one (or all) of
870904
/// its operands.
871905
///
872906
/// The ownership kind is set on construction and afterwards must be changed
873907
/// explicitly using setOwnershipKind().
874-
class OwnershipForwardingSingleValueInst : public SingleValueInstruction {
875-
ValueOwnershipKind ownershipKind;
876-
908+
class OwnershipForwardingSingleValueInst : public SingleValueInstruction,
909+
public OwnershipForwardingInst {
877910
protected:
878911
OwnershipForwardingSingleValueInst(SILInstructionKind kind,
879912
SILDebugLocation debugLoc, SILType ty,
880913
ValueOwnershipKind ownershipKind)
881914
: SingleValueInstruction(kind, debugLoc, ty),
882-
ownershipKind(ownershipKind) {
883-
assert(ownershipKind);
915+
OwnershipForwardingInst(kind, ownershipKind) {
916+
assert(classof(kind) && "classof missing new subclass?!");
884917
}
885918

886919
public:
887-
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
888-
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
889-
ownershipKind = newOwnershipKind;
890-
assert(ownershipKind);
920+
static bool classof(const SILNode *node) {
921+
if (auto *i = dyn_cast<SILInstruction>(node))
922+
return classof(i);
923+
return false;
924+
}
925+
926+
static bool classof(SILInstructionKind kind) {
927+
switch (kind) {
928+
case SILInstructionKind::MarkUninitializedInst:
929+
case SILInstructionKind::StructInst:
930+
case SILInstructionKind::ObjectInst:
931+
case SILInstructionKind::TupleInst:
932+
case SILInstructionKind::EnumInst:
933+
case SILInstructionKind::UncheckedEnumDataInst:
934+
case SILInstructionKind::SelectValueInst:
935+
case SILInstructionKind::OpenExistentialRefInst:
936+
case SILInstructionKind::InitExistentialRefInst:
937+
case SILInstructionKind::MarkDependenceInst:
938+
case SILInstructionKind::LinearFunctionInst:
939+
case SILInstructionKind::DifferentiableFunctionInst:
940+
return true;
941+
default:
942+
return false;
943+
}
944+
}
945+
946+
static bool classof(const SILInstruction *inst) {
947+
return classof(inst->getKind());
891948
}
892949
};
893950

@@ -4430,19 +4487,42 @@ class ConversionInst : public SingleValueInstruction {
44304487

44314488
/// A conversion inst that produces a static OwnershipKind set upon the
44324489
/// instruction's construction.
4433-
class OwnershipForwardingConversionInst : public ConversionInst {
4434-
ValueOwnershipKind ownershipKind;
4435-
4490+
class OwnershipForwardingConversionInst : public ConversionInst,
4491+
public OwnershipForwardingInst {
44364492
protected:
44374493
OwnershipForwardingConversionInst(SILInstructionKind kind,
44384494
SILDebugLocation debugLoc, SILType ty,
44394495
ValueOwnershipKind ownershipKind)
4440-
: ConversionInst(kind, debugLoc, ty), ownershipKind(ownershipKind) {}
4496+
: ConversionInst(kind, debugLoc, ty),
4497+
OwnershipForwardingInst(kind, ownershipKind) {
4498+
assert(classof(kind) && "classof missing subclass?!");
4499+
}
44414500

44424501
public:
4443-
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
4444-
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
4445-
ownershipKind = newOwnershipKind;
4502+
static bool classof(const SILNode *node) {
4503+
if (auto *i = dyn_cast<SILInstruction>(node))
4504+
return classof(i);
4505+
return false;
4506+
}
4507+
4508+
static bool classof(const SILInstruction *inst) {
4509+
return classof(inst->getKind());
4510+
}
4511+
4512+
static bool classof(SILInstructionKind kind) {
4513+
switch (kind) {
4514+
case SILInstructionKind::ConvertFunctionInst:
4515+
case SILInstructionKind::UpcastInst:
4516+
case SILInstructionKind::UncheckedRefCastInst:
4517+
case SILInstructionKind::UncheckedValueCastInst:
4518+
case SILInstructionKind::RefToBridgeObjectInst:
4519+
case SILInstructionKind::BridgeObjectToRefInst:
4520+
case SILInstructionKind::ThinToThickFunctionInst:
4521+
case SILInstructionKind::UnconditionalCheckedCastInst:
4522+
return true;
4523+
default:
4524+
return false;
4525+
}
44464526
}
44474527
};
44484528

@@ -5610,22 +5690,35 @@ class SelectEnumInstBase
56105690
};
56115691

56125692
/// A select enum inst that produces a static OwnershipKind.
5613-
class OwnershipForwardingSelectEnumInstBase : public SelectEnumInstBase {
5614-
ValueOwnershipKind ownershipKind;
5615-
5693+
class OwnershipForwardingSelectEnumInstBase : public SelectEnumInstBase,
5694+
public OwnershipForwardingInst {
56165695
protected:
56175696
OwnershipForwardingSelectEnumInstBase(
56185697
SILInstructionKind kind, SILDebugLocation debugLoc, SILType type,
56195698
bool defaultValue, Optional<ArrayRef<ProfileCounter>> caseCounts,
56205699
ProfileCounter defaultCount, ValueOwnershipKind ownershipKind)
56215700
: SelectEnumInstBase(kind, debugLoc, type, defaultValue, caseCounts,
56225701
defaultCount),
5623-
ownershipKind(ownershipKind) {}
5702+
OwnershipForwardingInst(kind, ownershipKind) {
5703+
assert(classof(kind) && "classof missing subclass");
5704+
}
56245705

56255706
public:
5626-
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
5627-
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
5628-
ownershipKind = newOwnershipKind;
5707+
static bool classof(const SILNode *node) {
5708+
if (auto *i = dyn_cast<SILInstruction>(node))
5709+
return classof(i);
5710+
return false;
5711+
}
5712+
5713+
static bool classof(const SILInstruction *i) { return classof(i->getKind()); }
5714+
5715+
static bool classof(SILInstructionKind kind) {
5716+
switch (kind) {
5717+
case SILInstructionKind::SelectEnumInst:
5718+
return true;
5719+
default:
5720+
return false;
5721+
}
56295722
}
56305723
};
56315724

@@ -7327,18 +7420,31 @@ class TermInst : public NonValueInstruction {
73277420
}
73287421
};
73297422

7330-
class OwnershipForwardingTermInst : public TermInst {
7331-
ValueOwnershipKind ownershipKind;
7332-
7423+
class OwnershipForwardingTermInst : public TermInst,
7424+
public OwnershipForwardingInst {
73337425
protected:
73347426
OwnershipForwardingTermInst(SILInstructionKind kind,
73357427
SILDebugLocation debugLoc,
73367428
ValueOwnershipKind ownershipKind)
7337-
: TermInst(kind, debugLoc), ownershipKind(ownershipKind) {}
7429+
: TermInst(kind, debugLoc), OwnershipForwardingInst(kind, ownershipKind) {
7430+
assert(classof(kind));
7431+
}
73387432

73397433
public:
7340-
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
7341-
void setOwnershipKind(ValueOwnershipKind newKind) { ownershipKind = newKind; }
7434+
static bool classof(const SILNode *node) {
7435+
if (auto *i = dyn_cast<SILInstruction>(node))
7436+
return classof(i);
7437+
return false;
7438+
}
7439+
7440+
static bool classof(const SILInstruction *inst) {
7441+
return classof(inst->getKind());
7442+
}
7443+
7444+
static bool classof(SILInstructionKind kind) {
7445+
return kind == SILInstructionKind::SwitchEnumInst ||
7446+
kind == SILInstructionKind::CheckedCastBranchInst;
7447+
}
73427448
};
73437449

73447450
/// UnreachableInst - Position in the code which would be undefined to reach.
@@ -8771,19 +8877,33 @@ SILFunction *ApplyInstBase<Impl, Base, false>::getCalleeFunction() const {
87718877
}
87728878

87738879
class OwnershipForwardingMultipleValueInstruction
8774-
: public MultipleValueInstruction {
8775-
ValueOwnershipKind ownershipKind;
8776-
8880+
: public MultipleValueInstruction,
8881+
public OwnershipForwardingInst {
87778882
public:
87788883
OwnershipForwardingMultipleValueInstruction(SILInstructionKind kind,
87798884
SILDebugLocation loc,
87808885
ValueOwnershipKind ownershipKind)
8781-
: MultipleValueInstruction(kind, loc), ownershipKind(ownershipKind) {}
8886+
: MultipleValueInstruction(kind, loc),
8887+
OwnershipForwardingInst(kind, ownershipKind) {
8888+
assert(classof(kind) && "Missing subclass from classof?!");
8889+
}
87828890

8783-
/// Returns the preferred ownership kind of this multiple value instruction.
8784-
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
8785-
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
8786-
ownershipKind = newOwnershipKind;
8891+
static bool classof(const SILNode *n) {
8892+
if (auto *i = dyn_cast<SILInstruction>(n))
8893+
return classof(i);
8894+
return false;
8895+
}
8896+
8897+
static bool classof(const SILInstruction *i) { return classof(i->getKind()); }
8898+
8899+
static bool classof(SILInstructionKind kind) {
8900+
switch (kind) {
8901+
case SILInstructionKind::DestructureTupleInst:
8902+
case SILInstructionKind::DestructureStructInst:
8903+
return true;
8904+
default:
8905+
return false;
8906+
}
87878907
}
87888908
};
87898909

@@ -8953,6 +9073,22 @@ inline bool Operand::isTypeDependent() const {
89539073
return getUser()->isTypeDependentOperand(*this);
89549074
}
89559075

9076+
inline bool OwnershipForwardingInst::classof(const SILInstruction *inst) {
9077+
return OwnershipForwardingSingleValueInst::classof(inst) ||
9078+
OwnershipForwardingTermInst::classof(inst) ||
9079+
OwnershipForwardingConversionInst::classof(inst) ||
9080+
OwnershipForwardingSelectEnumInstBase::classof(inst) ||
9081+
OwnershipForwardingMultipleValueInstruction::classof(inst);
9082+
}
9083+
9084+
inline bool OwnershipForwardingInst::classof(SILInstructionKind kind) {
9085+
return OwnershipForwardingSingleValueInst::classof(kind) ||
9086+
OwnershipForwardingTermInst::classof(kind) ||
9087+
OwnershipForwardingConversionInst::classof(kind) ||
9088+
OwnershipForwardingSelectEnumInstBase::classof(kind) ||
9089+
OwnershipForwardingMultipleValueInstruction::classof(kind);
9090+
}
9091+
89569092
} // end swift namespace
89579093

89589094
//===----------------------------------------------------------------------===//

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ FORWARD_ANY_OWNERSHIP_INST(DestructureTuple)
319319
OwnershipConstraint OwnershipConstraintClassifier::visit##INST##Inst( \
320320
INST##Inst *i) { \
321321
assert(i->getNumOperands() && "Expected to have non-zero operands"); \
322-
assert(isGuaranteedForwardingInst(i) && \
322+
assert(isGuaranteedForwardingValueKind(SILNodeKind(i->getKind())) && \
323323
"Expected an ownership forwarding inst"); \
324324
return {OwnershipKind::OWNERSHIP, \
325325
UseLifetimeConstraint::USE_LIFETIME_CONSTRAINT}; \

0 commit comments

Comments
 (0)