Skip to content

Commit 034b440

Browse files
committed
Clearly discriminate OperandOwnership::NonUse and TrivialUse.
A NonUse operand does not use the value itself, so it ignores ownership and does not require liveness. This is for operands that represent dependence on a type but are not actually passed the value of that type (e.g. they may refer an open_existential). This could be used for other dependence-only operands in the future. A TrivialUse operand has undefined ownership semantics, so it only handles values with ownership None. It does still require liveness. The name makes defining ownership for trivial operations perfectly obvious, increasing readability of OperandOwnership.cpp.
1 parent 949b0c0 commit 034b440

File tree

4 files changed

+97
-87
lines changed

4 files changed

+97
-87
lines changed

include/swift/SIL/SILValue.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -626,9 +626,15 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
626626
/// lifetime constraints.
627627
struct OperandOwnership {
628628
enum innerty : uint8_t {
629-
/// Uses of ownership None. These uses are incompatible with values that
630-
/// have ownership but are otherwise not verified.
631-
None,
629+
/// Operands that do not use the value. They only represent a dependence
630+
/// on a dominating definition and do not require liveness.
631+
/// (type-dependent operands)
632+
NonUse,
633+
634+
/// Uses that can only handle trivial values. The operand value must have
635+
/// None ownership. These uses require liveness but are otherwise
636+
/// unverified.
637+
TrivialUse,
632638

633639
/// Use the value only for the duration of the operation, which may have
634640
/// side effects. Requires an owned or guaranteed value.
@@ -726,8 +732,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
726732
/// Defined inline so the switch is eliminated for constant OperandOwnership.
727733
inline OwnershipConstraint OperandOwnership::getOwnershipConstraint() {
728734
switch (value) {
729-
case OperandOwnership::None:
735+
case OperandOwnership::TrivialUse:
730736
return {OwnershipKind::None, UseLifetimeConstraint::NonLifetimeEnding};
737+
case OperandOwnership::NonUse:
731738
case OperandOwnership::InstantaneousUse:
732739
case OperandOwnership::UnownedInstantaneousUse:
733740
case OperandOwnership::ForwardingUnowned:
@@ -770,7 +777,7 @@ ValueOwnershipKind::getForwardingOperandOwnership(bool allowUnowned) const {
770777
}
771778
llvm_unreachable("invalid value ownership");
772779
case OwnershipKind::None:
773-
return OperandOwnership::None;
780+
return OperandOwnership::TrivialUse;
774781
case OwnershipKind::Guaranteed:
775782
return OperandOwnership::ForwardingBorrow;
776783
case OwnershipKind::Owned:

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 77 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -121,63 +121,63 @@ SHOULD_NEVER_VISIT_INST(GetAsyncContinuation)
121121
}
122122

123123
// Instructions that require trivial operands.
124-
OPERAND_OWNERSHIP(None, AwaitAsyncContinuation)
125-
OPERAND_OWNERSHIP(None, AbortApply)
126-
OPERAND_OWNERSHIP(None, AddressToPointer)
127-
OPERAND_OWNERSHIP(None, AllocRef) // with tail operand
128-
OPERAND_OWNERSHIP(None, AllocRefDynamic) // with tail operand
129-
OPERAND_OWNERSHIP(None, BeginAccess)
130-
OPERAND_OWNERSHIP(None, BeginUnpairedAccess)
131-
OPERAND_OWNERSHIP(None, BindMemory)
132-
OPERAND_OWNERSHIP(None, CheckedCastAddrBranch)
133-
OPERAND_OWNERSHIP(None, CondBranch)
134-
OPERAND_OWNERSHIP(None, CondFail)
135-
OPERAND_OWNERSHIP(None, CopyAddr)
136-
OPERAND_OWNERSHIP(None, DeallocStack)
137-
OPERAND_OWNERSHIP(None, DebugValueAddr)
138-
OPERAND_OWNERSHIP(None, DeinitExistentialAddr)
139-
OPERAND_OWNERSHIP(None, DestroyAddr)
140-
OPERAND_OWNERSHIP(None, EndAccess)
141-
OPERAND_OWNERSHIP(None, EndApply)
142-
OPERAND_OWNERSHIP(None, EndUnpairedAccess)
143-
OPERAND_OWNERSHIP(None, GetAsyncContinuationAddr)
144-
OPERAND_OWNERSHIP(None, IndexAddr)
145-
OPERAND_OWNERSHIP(None, IndexRawPointer)
146-
OPERAND_OWNERSHIP(None, InitBlockStorageHeader)
147-
OPERAND_OWNERSHIP(None, InitEnumDataAddr)
148-
OPERAND_OWNERSHIP(None, InitExistentialAddr)
149-
OPERAND_OWNERSHIP(None, InitExistentialMetatype)
150-
OPERAND_OWNERSHIP(None, InjectEnumAddr)
151-
OPERAND_OWNERSHIP(None, IsUnique)
152-
OPERAND_OWNERSHIP(None, Load)
153-
OPERAND_OWNERSHIP(None, LoadBorrow)
154-
OPERAND_OWNERSHIP(None, MarkFunctionEscape)
155-
OPERAND_OWNERSHIP(None, ObjCExistentialMetatypeToObject)
156-
OPERAND_OWNERSHIP(None, ObjCMetatypeToObject)
157-
OPERAND_OWNERSHIP(None, ObjCToThickMetatype)
158-
OPERAND_OWNERSHIP(None, OpenExistentialAddr)
159-
OPERAND_OWNERSHIP(None, OpenExistentialMetatype)
160-
OPERAND_OWNERSHIP(None, PointerToAddress)
161-
OPERAND_OWNERSHIP(None, PointerToThinFunction)
162-
OPERAND_OWNERSHIP(None, ProjectBlockStorage)
163-
OPERAND_OWNERSHIP(None, ProjectValueBuffer)
164-
OPERAND_OWNERSHIP(None, RawPointerToRef)
165-
OPERAND_OWNERSHIP(None, SelectEnumAddr)
166-
OPERAND_OWNERSHIP(None, SelectValue)
167-
OPERAND_OWNERSHIP(None, StructElementAddr)
168-
OPERAND_OWNERSHIP(None, SwitchEnumAddr)
169-
OPERAND_OWNERSHIP(None, SwitchValue)
170-
OPERAND_OWNERSHIP(None, TailAddr)
171-
OPERAND_OWNERSHIP(None, ThickToObjCMetatype)
172-
OPERAND_OWNERSHIP(None, ThinFunctionToPointer)
173-
OPERAND_OWNERSHIP(None, ThinToThickFunction)
174-
OPERAND_OWNERSHIP(None, TupleElementAddr)
175-
OPERAND_OWNERSHIP(None, UncheckedAddrCast)
176-
OPERAND_OWNERSHIP(None, UncheckedRefCastAddr)
177-
OPERAND_OWNERSHIP(None, UncheckedTakeEnumDataAddr)
178-
OPERAND_OWNERSHIP(None, UnconditionalCheckedCastAddr)
179-
OPERAND_OWNERSHIP(None, AllocValueBuffer)
180-
OPERAND_OWNERSHIP(None, DeallocValueBuffer)
124+
OPERAND_OWNERSHIP(TrivialUse, AwaitAsyncContinuation)
125+
OPERAND_OWNERSHIP(TrivialUse, AbortApply)
126+
OPERAND_OWNERSHIP(TrivialUse, AddressToPointer)
127+
OPERAND_OWNERSHIP(TrivialUse, AllocRef) // with tail operand
128+
OPERAND_OWNERSHIP(TrivialUse, AllocRefDynamic) // with tail operand
129+
OPERAND_OWNERSHIP(TrivialUse, BeginAccess)
130+
OPERAND_OWNERSHIP(TrivialUse, BeginUnpairedAccess)
131+
OPERAND_OWNERSHIP(TrivialUse, BindMemory)
132+
OPERAND_OWNERSHIP(TrivialUse, CheckedCastAddrBranch)
133+
OPERAND_OWNERSHIP(TrivialUse, CondBranch)
134+
OPERAND_OWNERSHIP(TrivialUse, CondFail)
135+
OPERAND_OWNERSHIP(TrivialUse, CopyAddr)
136+
OPERAND_OWNERSHIP(TrivialUse, DeallocStack)
137+
OPERAND_OWNERSHIP(TrivialUse, DebugValueAddr)
138+
OPERAND_OWNERSHIP(TrivialUse, DeinitExistentialAddr)
139+
OPERAND_OWNERSHIP(TrivialUse, DestroyAddr)
140+
OPERAND_OWNERSHIP(TrivialUse, EndAccess)
141+
OPERAND_OWNERSHIP(TrivialUse, EndApply)
142+
OPERAND_OWNERSHIP(TrivialUse, EndUnpairedAccess)
143+
OPERAND_OWNERSHIP(TrivialUse, GetAsyncContinuationAddr)
144+
OPERAND_OWNERSHIP(TrivialUse, IndexAddr)
145+
OPERAND_OWNERSHIP(TrivialUse, IndexRawPointer)
146+
OPERAND_OWNERSHIP(TrivialUse, InitBlockStorageHeader)
147+
OPERAND_OWNERSHIP(TrivialUse, InitEnumDataAddr)
148+
OPERAND_OWNERSHIP(TrivialUse, InitExistentialAddr)
149+
OPERAND_OWNERSHIP(TrivialUse, InitExistentialMetatype)
150+
OPERAND_OWNERSHIP(TrivialUse, InjectEnumAddr)
151+
OPERAND_OWNERSHIP(TrivialUse, IsUnique)
152+
OPERAND_OWNERSHIP(TrivialUse, Load)
153+
OPERAND_OWNERSHIP(TrivialUse, LoadBorrow)
154+
OPERAND_OWNERSHIP(TrivialUse, MarkFunctionEscape)
155+
OPERAND_OWNERSHIP(TrivialUse, ObjCExistentialMetatypeToObject)
156+
OPERAND_OWNERSHIP(TrivialUse, ObjCMetatypeToObject)
157+
OPERAND_OWNERSHIP(TrivialUse, ObjCToThickMetatype)
158+
OPERAND_OWNERSHIP(TrivialUse, OpenExistentialAddr)
159+
OPERAND_OWNERSHIP(TrivialUse, OpenExistentialMetatype)
160+
OPERAND_OWNERSHIP(TrivialUse, PointerToAddress)
161+
OPERAND_OWNERSHIP(TrivialUse, PointerToThinFunction)
162+
OPERAND_OWNERSHIP(TrivialUse, ProjectBlockStorage)
163+
OPERAND_OWNERSHIP(TrivialUse, ProjectValueBuffer)
164+
OPERAND_OWNERSHIP(TrivialUse, RawPointerToRef)
165+
OPERAND_OWNERSHIP(TrivialUse, SelectEnumAddr)
166+
OPERAND_OWNERSHIP(TrivialUse, SelectValue)
167+
OPERAND_OWNERSHIP(TrivialUse, StructElementAddr)
168+
OPERAND_OWNERSHIP(TrivialUse, SwitchEnumAddr)
169+
OPERAND_OWNERSHIP(TrivialUse, SwitchValue)
170+
OPERAND_OWNERSHIP(TrivialUse, TailAddr)
171+
OPERAND_OWNERSHIP(TrivialUse, ThickToObjCMetatype)
172+
OPERAND_OWNERSHIP(TrivialUse, ThinFunctionToPointer)
173+
OPERAND_OWNERSHIP(TrivialUse, ThinToThickFunction)
174+
OPERAND_OWNERSHIP(TrivialUse, TupleElementAddr)
175+
OPERAND_OWNERSHIP(TrivialUse, UncheckedAddrCast)
176+
OPERAND_OWNERSHIP(TrivialUse, UncheckedRefCastAddr)
177+
OPERAND_OWNERSHIP(TrivialUse, UncheckedTakeEnumDataAddr)
178+
OPERAND_OWNERSHIP(TrivialUse, UnconditionalCheckedCastAddr)
179+
OPERAND_OWNERSHIP(TrivialUse, AllocValueBuffer)
180+
OPERAND_OWNERSHIP(TrivialUse, DeallocValueBuffer)
181181

182182
// Use an owned or guaranteed value only for the duration of the operation.
183183
OPERAND_OWNERSHIP(InstantaneousUse, ExistentialMetatype)
@@ -263,13 +263,14 @@ OPERAND_OWNERSHIP(ForwardingBorrow, OpenExistentialBoxValue)
263263
OPERAND_OWNERSHIP(EndBorrow, EndBorrow)
264264

265265
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
266-
OPERAND_OWNERSHIP(None, Load##Name)
266+
OPERAND_OWNERSHIP(TrivialUse, Load##Name)
267267
#define ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
268268
OPERAND_OWNERSHIP(DestroyingConsume, Name##Release)
269269
#define SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
270270
NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, "...") \
271271
ALWAYS_LOADABLE_CHECKED_REF_STORAGE(Name, "...")
272-
#define UNCHECKED_REF_STORAGE(Name, ...) OPERAND_OWNERSHIP(None, Name##ToRef)
272+
#define UNCHECKED_REF_STORAGE(Name, ...) \
273+
OPERAND_OWNERSHIP(TrivialUse, Name##ToRef)
273274
#include "swift/AST/ReferenceStorage.def"
274275

275276
#define NEVER_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
@@ -345,7 +346,7 @@ OperandOwnershipClassifier::visitBeginBorrowInst(BeginBorrowInst *borrow) {
345346
case OwnershipKind::Any:
346347
llvm_unreachable("invalid value ownership");
347348
case OwnershipKind::None:
348-
return OperandOwnership::None;
349+
return OperandOwnership::TrivialUse;
349350
case OwnershipKind::Unowned:
350351
// FIXME: disallow borrowing an Unowned value. Temporarily model it as an
351352
// instantaneous use until SILGenFunction::emitClassMemberDestruction is
@@ -365,7 +366,7 @@ visitDeallocPartialRefInst(DeallocPartialRefInst *i) {
365366
if (getValue() == i->getInstance()) {
366367
return OperandOwnership::DestroyingConsume;
367368
}
368-
return OperandOwnership::None;
369+
return OperandOwnership::TrivialUse;
369370
}
370371

371372
OperandOwnership
@@ -395,7 +396,7 @@ OperandOwnershipClassifier::visitStoreBorrowInst(StoreBorrowInst *i) {
395396
if (getValue() == i->getSrc()) {
396397
return OperandOwnership::ForwardingBorrow;
397398
}
398-
return OperandOwnership::None;
399+
return OperandOwnership::TrivialUse;
399400
}
400401

401402
static OperandOwnership getFunctionArgOwnership(SILArgumentConvention argConv) {
@@ -428,7 +429,7 @@ OperandOwnershipClassifier::visitFullApply(FullApplySite apply) {
428429
// Before considering conventions, filter all (trivial) indirect
429430
// arguments. This also rules out result arguments.
430431
if (getValue()->getType().isAddress()) {
431-
return OperandOwnership::None;
432+
return OperandOwnership::TrivialUse;
432433
}
433434
SILArgumentConvention argConv = apply.isCalleeOperand(op)
434435
? SILArgumentConvention(apply.getSubstCalleeType()->getCalleeConvention())
@@ -472,7 +473,7 @@ OperandOwnershipClassifier::visitPartialApplyInst(PartialApplyInst *i) {
472473
OperandOwnership OperandOwnershipClassifier::visitYieldInst(YieldInst *i) {
473474
// Before considering conventions, filter all indirect arguments.
474475
if (getValue()->getType().isAddress()) {
475-
return OperandOwnership::None;
476+
return OperandOwnership::TrivialUse;
476477
}
477478
auto fnType = i->getFunction()->getLoweredFunctionType();
478479
SILArgumentConvention argConv(
@@ -486,7 +487,7 @@ OperandOwnership OperandOwnershipClassifier::visitReturnInst(ReturnInst *i) {
486487
case OwnershipKind::Guaranteed:
487488
llvm_unreachable("invalid value ownership");
488489
case OwnershipKind::None:
489-
return OperandOwnership::None;
490+
return OperandOwnership::TrivialUse;
490491
case OwnershipKind::Unowned:
491492
return OperandOwnership::UnownedInstantaneousUse;
492493
case OwnershipKind::Owned:
@@ -496,7 +497,7 @@ OperandOwnership OperandOwnershipClassifier::visitReturnInst(ReturnInst *i) {
496497

497498
OperandOwnership OperandOwnershipClassifier::visitAssignInst(AssignInst *i) {
498499
if (getValue() != i->getSrc()) {
499-
return OperandOwnership::None;
500+
return OperandOwnership::TrivialUse;
500501
}
501502
return OperandOwnership::DestroyingConsume;
502503
}
@@ -507,14 +508,14 @@ OperandOwnershipClassifier::visitAssignByWrapperInst(AssignByWrapperInst *i) {
507508
return OperandOwnership::DestroyingConsume;
508509
}
509510
if (getValue() == i->getDest()) {
510-
return OperandOwnership::None;
511+
return OperandOwnership::TrivialUse;
511512
}
512513
return OperandOwnership::InstantaneousUse; // initializer/setter closure
513514
}
514515

515516
OperandOwnership OperandOwnershipClassifier::visitStoreInst(StoreInst *i) {
516517
if (getValue() != i->getSrc()) {
517-
return OperandOwnership::None;
518+
return OperandOwnership::TrivialUse;
518519
}
519520
return OperandOwnership::DestroyingConsume;
520521
}
@@ -560,7 +561,7 @@ struct OperandOwnershipBuiltinClassifier
560561
OperandOwnership visitLLVMIntrinsic(BuiltinInst *bi, llvm::Intrinsic::ID id) {
561562
// LLVM intrinsics do not traffic in ownership, so if we have a result, it
562563
// must be trivial.
563-
return OperandOwnership::None;
564+
return OperandOwnership::TrivialUse;
564565
}
565566

566567
// BUILTIN_TYPE_CHECKER_OPERATION does not live past the type checker.
@@ -741,10 +742,10 @@ BUILTIN_OPERAND_OWNERSHIP(ForwardingBorrow, AutoDiffAllocateSubcontext)
741742
BUILTIN_OPERAND_OWNERSHIP(ForwardingBorrow, AutoDiffProjectTopLevelSubcontext)
742743

743744
// FIXME: ConvertTaskToJob is documented as taking NativePointer. It's operand's
744-
// ownership should be 'None'.
745+
// ownership should be 'TrivialUse'.
745746
BUILTIN_OPERAND_OWNERSHIP(ForwardingConsume, ConvertTaskToJob)
746747

747-
BUILTIN_OPERAND_OWNERSHIP(None, AutoDiffCreateLinearMapContext)
748+
BUILTIN_OPERAND_OWNERSHIP(TrivialUse, AutoDiffCreateLinearMapContext)
748749

749750
#undef BUILTIN_OPERAND_OWNERSHIP
750751

@@ -776,14 +777,12 @@ OperandOwnership OperandOwnershipClassifier::visitBuiltinInst(BuiltinInst *bi) {
776777
//===----------------------------------------------------------------------===//
777778

778779
OperandOwnership Operand::getOperandOwnership() const {
779-
// We consider type dependent uses to be instantaneous uses.
780-
//
781-
// NOTE: We could instead try to exclude type dependent uses from our system,
782-
// but that adds a bunch of Optionals and unnecessary types. This doesn't hurt
783-
// anything and allows us to eliminate Optionals and thus confusion in between
784-
// Optional::None and OwnershipKind::None.
780+
// NOTE: NonUse distinguishes itself from InstantaneousUse because it does not
781+
// require liveness. Discrimating such uses in the enum avoids the need to
782+
// return an Optional<OperandOwnership>::None, which could be confused with
783+
// OwnershipKind::None.
785784
if (isTypeDependent())
786-
return OperandOwnership::InstantaneousUse;
785+
return OperandOwnership::NonUse;
787786

788787
// If we do not have ownership enabled, just return any. This ensures that we
789788
// do not have any consuming uses and everything from an ownership perspective

lib/SIL/IR/SILValue.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,13 @@ SILFunction *Operand::getParentFunction() const {
322322
/// Return true if this use can accept Unowned values.
323323
static bool canAcceptUnownedValue(OperandOwnership operandOwnership) {
324324
switch (operandOwnership) {
325+
case OperandOwnership::NonUse:
325326
case OperandOwnership::UnownedInstantaneousUse:
326327
case OperandOwnership::ForwardingUnowned:
327328
case OperandOwnership::PointerEscape:
328329
case OperandOwnership::BitwiseEscape:
329330
return true;
330-
case OperandOwnership::None:
331+
case OperandOwnership::TrivialUse:
331332
case OperandOwnership::InstantaneousUse:
332333
case OperandOwnership::Borrow:
333334
case OperandOwnership::DestroyingConsume:
@@ -391,8 +392,10 @@ llvm::raw_ostream &swift::operator<<(llvm::raw_ostream &os,
391392

392393
StringRef OperandOwnership::asString() const {
393394
switch (value) {
394-
case OperandOwnership::None:
395-
return "none";
395+
case OperandOwnership::NonUse:
396+
return "non-use";
397+
case OperandOwnership::TrivialUse:
398+
return "trivial-use";
396399
case OperandOwnership::InstantaneousUse:
397400
return "instantaneous";
398401
case OperandOwnership::UnownedInstantaneousUse:

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,11 +878,12 @@ Optional<ForwardingOperand> ForwardingOperand::get(Operand *use) {
878878
}
879879
#ifndef NDEBUG
880880
switch (use->getOperandOwnership()) {
881-
case OperandOwnership::None:
882881
case OperandOwnership::ForwardingUnowned:
883882
case OperandOwnership::ForwardingConsume:
884883
case OperandOwnership::ForwardingBorrow:
885884
break;
885+
case OperandOwnership::NonUse:
886+
case OperandOwnership::TrivialUse:
886887
case OperandOwnership::InstantaneousUse:
887888
case OperandOwnership::UnownedInstantaneousUse:
888889
case OperandOwnership::PointerEscape:

0 commit comments

Comments
 (0)