Skip to content

Commit 93d1524

Browse files
authored
Merge pull request swiftlang#34634 from gottesmm/pr-88f0c52a3c1db5fb272598e5c5596ce3594d804c
[ownership] Make checked_cast_br, destructure_struct, and destructure_tuple real forwarding instructions
2 parents 268bf98 + c4adc64 commit 93d1524

File tree

8 files changed

+295
-314
lines changed

8 files changed

+295
-314
lines changed

include/swift/SIL/OwnershipUtils.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,20 @@ bool isOwnedForwardingInstruction(SILInstruction *inst);
6666
/// previous terminator.
6767
bool isOwnedForwardingValue(SILValue value);
6868

69+
class ForwardingOperand {
70+
Operand *use;
71+
72+
ForwardingOperand(Operand *use) : use(use) {}
73+
74+
public:
75+
static Optional<ForwardingOperand> get(Operand *use);
76+
77+
ValueOwnershipKind getOwnershipKind() const;
78+
void setOwnershipKind(ValueOwnershipKind newKind) const;
79+
void replaceOwnershipKind(ValueOwnershipKind oldKind,
80+
ValueOwnershipKind newKind) const;
81+
};
82+
6983
/// Returns true if the instruction is a 'reborrow'.
7084
bool isReborrowInstruction(const SILInstruction *inst);
7185

include/swift/SIL/SILInstruction.h

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,12 @@ class MultipleValueInstructionTrailingObjects<Derived, DerivedResult,
10951095
return { ptr, NumResults };
10961096
}
10971097

1098+
MutableArrayRef<DerivedResult> getAllResultsBuffer() {
1099+
auto *ptr = this->TrailingObjects::template
1100+
getTrailingObjects<DerivedResult>();
1101+
return { ptr, NumResults };
1102+
}
1103+
10981104
SILInstructionResultArray getAllResults() const {
10991105
// Our results start at element 1 since we stash the pointer to our parent
11001106
// MultipleValueInstruction in the 0 elt slot. This allows all
@@ -8126,23 +8132,20 @@ class DynamicMethodBranchInst
81268132
};
81278133

81288134
/// The base class for cast instructions which are terminators.
8129-
class CastBranchInstBase : public TermInst {
8135+
template <typename BaseTy> class CastBranchInstBase : public BaseTy {
81308136
std::array<SILSuccessor, 2> DestBBs;
81318137

81328138
public:
8133-
8139+
template <typename... ArgTys>
81348140
CastBranchInstBase(SILInstructionKind K, SILDebugLocation DebugLoc,
81358141
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB,
8136-
ProfileCounter Target1Count = ProfileCounter(),
8137-
ProfileCounter Target2Count = ProfileCounter()) :
8138-
TermInst(K, DebugLoc),
8139-
DestBBs{{{this, SuccessBB, Target1Count},
8140-
{this, FailureBB, Target2Count}}}
8141-
{}
8142+
ProfileCounter Target1Count, ProfileCounter Target2Count,
8143+
ArgTys &&... args)
8144+
: BaseTy(K, DebugLoc, std::forward<ArgTys>(args)...),
8145+
DestBBs{{{this, SuccessBB, Target1Count},
8146+
{this, FailureBB, Target2Count}}} {}
81428147

8143-
SuccessorListTy getSuccessors() {
8144-
return DestBBs;
8145-
}
8148+
TermInst::SuccessorListTy getSuccessors() { return DestBBs; }
81468149

81478150
SILBasicBlock *getSuccessBB() { return DestBBs[0]; }
81488151
const SILBasicBlock *getSuccessBB() const { return DestBBs[0]; }
@@ -8157,7 +8160,7 @@ class CastBranchInstBase : public TermInst {
81578160

81588161
/// The base class for cast instructions which are terminators and have a
81598162
/// CastConsumptionKind.
8160-
class CastBranchWithConsumptionKindBase : public CastBranchInstBase {
8163+
class CastBranchWithConsumptionKindBase : public CastBranchInstBase<TermInst> {
81618164
CastConsumptionKind ConsumptionKind;
81628165

81638166
public:
@@ -8250,11 +8253,10 @@ class AddrCastInstBase
82508253
/// Perform a checked cast operation and branch on whether the cast succeeds.
82518254
/// The success branch destination block receives the cast result as a BB
82528255
/// argument.
8253-
class CheckedCastBranchInst final:
8254-
public UnaryInstructionWithTypeDependentOperandsBase<
8255-
SILInstructionKind::CheckedCastBranchInst,
8256-
CheckedCastBranchInst,
8257-
CastBranchInstBase> {
8256+
class CheckedCastBranchInst final
8257+
: public UnaryInstructionWithTypeDependentOperandsBase<
8258+
SILInstructionKind::CheckedCastBranchInst, CheckedCastBranchInst,
8259+
CastBranchInstBase<OwnershipForwardingTermInst>> {
82588260
friend SILBuilder;
82598261

82608262
SILType DestLoweredTy;
@@ -8266,12 +8268,12 @@ class CheckedCastBranchInst final:
82668268
ArrayRef<SILValue> TypeDependentOperands,
82678269
SILType DestLoweredTy, CanType DestFormalTy,
82688270
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB,
8269-
ProfileCounter Target1Count, ProfileCounter Target2Count)
8270-
: UnaryInstructionWithTypeDependentOperandsBase(DebugLoc, Operand,
8271-
TypeDependentOperands,
8272-
SuccessBB, FailureBB, Target1Count, Target2Count),
8273-
DestLoweredTy(DestLoweredTy),
8274-
DestFormalTy(DestFormalTy),
8271+
ProfileCounter Target1Count,
8272+
ProfileCounter Target2Count)
8273+
: UnaryInstructionWithTypeDependentOperandsBase(
8274+
DebugLoc, Operand, TypeDependentOperands, SuccessBB, FailureBB,
8275+
Target1Count, Target2Count, Operand.getOwnershipKind()),
8276+
DestLoweredTy(DestLoweredTy), DestFormalTy(DestFormalTy),
82758277
IsExact(IsExact) {}
82768278

82778279
static CheckedCastBranchInst *
@@ -8297,23 +8299,23 @@ class CheckedCastBranchInst final:
82978299
class CheckedCastValueBranchInst final
82988300
: public UnaryInstructionWithTypeDependentOperandsBase<
82998301
SILInstructionKind::CheckedCastValueBranchInst,
8300-
CheckedCastValueBranchInst,
8301-
CastBranchInstBase> {
8302+
CheckedCastValueBranchInst, CastBranchInstBase<TermInst>> {
83028303
friend SILBuilder;
83038304

83048305
CanType SourceFormalTy;
83058306
SILType DestLoweredTy;
83068307
CanType DestFormalTy;
83078308

8308-
CheckedCastValueBranchInst(SILDebugLocation DebugLoc,
8309-
SILValue Operand, CanType SourceFormalTy,
8309+
CheckedCastValueBranchInst(SILDebugLocation DebugLoc, SILValue Operand,
8310+
CanType SourceFormalTy,
83108311
ArrayRef<SILValue> TypeDependentOperands,
83118312
SILType DestLoweredTy, CanType DestFormalTy,
83128313
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB)
8313-
: UnaryInstructionWithTypeDependentOperandsBase(DebugLoc, Operand,
8314-
TypeDependentOperands, SuccessBB, FailureBB),
8315-
SourceFormalTy(SourceFormalTy),
8316-
DestLoweredTy(DestLoweredTy), DestFormalTy(DestFormalTy) {}
8314+
: UnaryInstructionWithTypeDependentOperandsBase(
8315+
DebugLoc, Operand, TypeDependentOperands, SuccessBB, FailureBB,
8316+
ProfileCounter(), ProfileCounter()),
8317+
SourceFormalTy(SourceFormalTy), DestLoweredTy(DestLoweredTy),
8318+
DestFormalTy(DestFormalTy) {}
83178319

83188320
static CheckedCastValueBranchInst *
83198321
create(SILDebugLocation DebugLoc,
@@ -8757,6 +8759,23 @@ SILFunction *ApplyInstBase<Impl, Base, false>::getCalleeFunction() const {
87578759
}
87588760
}
87598761

8762+
class OwnershipForwardingMultipleValueInstruction
8763+
: public MultipleValueInstruction {
8764+
ValueOwnershipKind ownershipKind;
8765+
8766+
public:
8767+
OwnershipForwardingMultipleValueInstruction(SILInstructionKind kind,
8768+
SILDebugLocation loc,
8769+
ValueOwnershipKind ownershipKind)
8770+
: MultipleValueInstruction(kind, loc), ownershipKind(ownershipKind) {}
8771+
8772+
/// Returns the preferred ownership kind of this multiple value instruction.
8773+
ValueOwnershipKind getOwnershipKind() const { return ownershipKind; }
8774+
void setOwnershipKind(ValueOwnershipKind newOwnershipKind) {
8775+
ownershipKind = newOwnershipKind;
8776+
}
8777+
};
8778+
87608779
/// A result for the destructure_struct instruction. See documentation for
87618780
/// destructure_struct for more information.
87628781
class DestructureStructResult final : public MultipleValueInstructionResult {
@@ -8780,15 +8799,15 @@ class DestructureStructResult final : public MultipleValueInstructionResult {
87808799
/// struct's fields.
87818800
class DestructureStructInst final
87828801
: public UnaryInstructionBase<SILInstructionKind::DestructureStructInst,
8783-
MultipleValueInstruction>,
8784-
public MultipleValueInstructionTrailingObjects<
8785-
DestructureStructInst, DestructureStructResult> {
8802+
OwnershipForwardingMultipleValueInstruction>,
8803+
public MultipleValueInstructionTrailingObjects<DestructureStructInst,
8804+
DestructureStructResult> {
87868805
friend TrailingObjects;
87878806

87888807
DestructureStructInst(SILModule &M, SILDebugLocation Loc, SILValue Operand,
87898808
ArrayRef<SILType> Types,
87908809
ArrayRef<ValueOwnershipKind> OwnershipKinds)
8791-
: UnaryInstructionBase(Loc, Operand),
8810+
: UnaryInstructionBase(Loc, Operand, Operand.getOwnershipKind()),
87928811
MultipleValueInstructionTrailingObjects(this, Types, OwnershipKinds) {}
87938812

87948813
public:
@@ -8829,15 +8848,15 @@ class DestructureTupleResult final : public MultipleValueInstructionResult {
88298848
/// tuples's elements.
88308849
class DestructureTupleInst final
88318850
: public UnaryInstructionBase<SILInstructionKind::DestructureTupleInst,
8832-
MultipleValueInstruction>,
8833-
public MultipleValueInstructionTrailingObjects<
8834-
DestructureTupleInst, DestructureTupleResult> {
8851+
OwnershipForwardingMultipleValueInstruction>,
8852+
public MultipleValueInstructionTrailingObjects<DestructureTupleInst,
8853+
DestructureTupleResult> {
88358854
friend TrailingObjects;
88368855

88378856
DestructureTupleInst(SILModule &M, SILDebugLocation Loc, SILValue Operand,
88388857
ArrayRef<SILType> Types,
88398858
ArrayRef<ValueOwnershipKind> OwnershipKinds)
8840-
: UnaryInstructionBase(Loc, Operand),
8859+
: UnaryInstructionBase(Loc, Operand, Operand.getOwnershipKind()),
88418860
MultipleValueInstructionTrailingObjects(this, Types, OwnershipKinds) {}
88428861

88438862
public:

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 11 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,6 @@ class OperandOwnershipKindClassifier
7373
return getOwnershipKind() == ValueOwnershipKind::None;
7474
}
7575

76-
OperandOwnershipKindMap visitForwardingInst(SILInstruction *i,
77-
ArrayRef<Operand> ops);
78-
OperandOwnershipKindMap visitForwardingInst(SILInstruction *i) {
79-
return visitForwardingInst(i, i->getAllOperands());
80-
}
81-
8276
OperandOwnershipKindMap
8377
visitApplyParameter(ValueOwnershipKind requiredConvention,
8478
UseLifetimeConstraint requirement);
@@ -299,38 +293,12 @@ ACCEPTS_ANY_OWNERSHIP_INST(ConvertEscapeToNoEscape)
299293
#include "swift/AST/ReferenceStorage.def"
300294
#undef ACCEPTS_ANY_OWNERSHIP_INST
301295

302-
OperandOwnershipKindMap
303-
OperandOwnershipKindClassifier::visitForwardingInst(SILInstruction *i,
304-
ArrayRef<Operand> ops) {
305-
assert(i->getNumOperands() && "Expected to have non-zero operands");
306-
assert(isOwnershipForwardingInst(i) &&
307-
"Expected to have an ownership forwarding inst");
308-
309-
// Merge all of the ownership of our operands. If we get back a .none from the
310-
// merge, then we return an empty compatibility map. This ensures that we will
311-
// not be compatible with /any/ input triggering a special error in the
312-
// ownership verifier.
313-
Optional<ValueOwnershipKind> optionalKind =
314-
ValueOwnershipKind::merge(makeOptionalTransformRange(
315-
ops, [&i](const Operand &op) -> Optional<ValueOwnershipKind> {
316-
if (i->isTypeDependentOperand(op))
317-
return None;
318-
return op.get().getOwnershipKind();
319-
}));
320-
if (!optionalKind)
321-
return Map();
322-
323-
auto kind = optionalKind.getValue();
324-
if (kind == ValueOwnershipKind::None)
325-
return Map::allLive();
326-
auto lifetimeConstraint = kind.getForwardingLifetimeConstraint();
327-
return Map::compatibilityMap(kind, lifetimeConstraint);
328-
}
329-
330296
#define FORWARD_ANY_OWNERSHIP_INST(INST) \
331297
OperandOwnershipKindMap OperandOwnershipKindClassifier::visit##INST##Inst( \
332298
INST##Inst *i) { \
333-
return visitForwardingInst(i); \
299+
auto kind = i->getOwnershipKind(); \
300+
auto lifetimeConstraint = kind.getForwardingLifetimeConstraint(); \
301+
return Map::compatibilityMap(kind, lifetimeConstraint); \
334302
}
335303
FORWARD_ANY_OWNERSHIP_INST(Tuple)
336304
FORWARD_ANY_OWNERSHIP_INST(Struct)
@@ -344,12 +312,12 @@ FORWARD_ANY_OWNERSHIP_INST(RefToBridgeObject)
344312
FORWARD_ANY_OWNERSHIP_INST(BridgeObjectToRef)
345313
FORWARD_ANY_OWNERSHIP_INST(UnconditionalCheckedCast)
346314
FORWARD_ANY_OWNERSHIP_INST(UncheckedEnumData)
347-
FORWARD_ANY_OWNERSHIP_INST(DestructureStruct)
348-
FORWARD_ANY_OWNERSHIP_INST(DestructureTuple)
349315
FORWARD_ANY_OWNERSHIP_INST(InitExistentialRef)
350316
FORWARD_ANY_OWNERSHIP_INST(DifferentiableFunction)
351317
FORWARD_ANY_OWNERSHIP_INST(LinearFunction)
352318
FORWARD_ANY_OWNERSHIP_INST(UncheckedValueCast)
319+
FORWARD_ANY_OWNERSHIP_INST(DestructureStruct)
320+
FORWARD_ANY_OWNERSHIP_INST(DestructureTuple)
353321
#undef FORWARD_ANY_OWNERSHIP_INST
354322

355323
// An instruction that forwards a constant ownership or trivial ownership.
@@ -395,7 +363,9 @@ OperandOwnershipKindClassifier::visitSelectEnumInst(SelectEnumInst *i) {
395363
return Map::allLive();
396364
}
397365

398-
return visitForwardingInst(i, i->getAllOperands().drop_front());
366+
auto kind = i->getOwnershipKind();
367+
auto lifetimeConstraint = kind.getForwardingLifetimeConstraint();
368+
return Map::compatibilityMap(kind, lifetimeConstraint);
399369
}
400370

401371
OperandOwnershipKindMap
@@ -458,31 +428,9 @@ OperandOwnershipKindClassifier::visitSwitchEnumInst(SwitchEnumInst *sei) {
458428
OperandOwnershipKindMap
459429
OperandOwnershipKindClassifier::visitCheckedCastBranchInst(
460430
CheckedCastBranchInst *ccbi) {
461-
// TODO: Simplify this using ValueOwnershipKind::merge.
462-
Optional<OperandOwnershipKindMap> map;
463-
for (auto argArray : ccbi->getSuccessorBlockArgumentLists()) {
464-
assert(!argArray.empty());
465-
466-
auto argOwnershipKind = argArray[getOperandIndex()]->getOwnershipKind();
467-
// If we do not have a map yet, initialize it and continue.
468-
if (!map) {
469-
auto lifetimeConstraint =
470-
argOwnershipKind.getForwardingLifetimeConstraint();
471-
map = Map::compatibilityMap(argOwnershipKind, lifetimeConstraint);
472-
continue;
473-
}
474-
475-
// Otherwise, make sure that we can accept the rest of our
476-
// arguments. If not, we return an empty ownership kind to make
477-
// sure that we flag everything as an error.
478-
if (map->canAcceptKind(argOwnershipKind)) {
479-
continue;
480-
}
481-
482-
return OperandOwnershipKindMap();
483-
}
484-
485-
return map.getValue();
431+
auto kind = getOwnershipKind();
432+
auto lifetimeConstraint = kind.getForwardingLifetimeConstraint();
433+
return Map::compatibilityMap(kind, lifetimeConstraint);
486434
}
487435

488436
//// FIX THIS HERE

0 commit comments

Comments
 (0)