Skip to content

Commit 6c3af65

Browse files
committed
[ownership] Add a simple ForwardingOperand ADT and use it in a few places.
1 parent d1b555f commit 6c3af65

File tree

4 files changed

+182
-72
lines changed

4 files changed

+182
-72
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: 6 additions & 0 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

lib/SIL/Utils/OwnershipUtils.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,3 +827,161 @@ swift::getSingleOwnedValueIntroducer(SILValue inputValue) {
827827

828828
llvm_unreachable("Should never hit this");
829829
}
830+
831+
//===----------------------------------------------------------------------===//
832+
// Forwarding Operand
833+
//===----------------------------------------------------------------------===//
834+
835+
Optional<ForwardingOperand> ForwardingOperand::get(Operand *use) {
836+
auto *user = use->getUser();
837+
if (isa<OwnershipForwardingTermInst>(user))
838+
return ForwardingOperand(use);
839+
if (isa<OwnershipForwardingSingleValueInst>(user))
840+
return ForwardingOperand(use);
841+
if (isa<OwnershipForwardingConversionInst>(user))
842+
return ForwardingOperand(use);
843+
if (isa<OwnershipForwardingSelectEnumInstBase>(user))
844+
return ForwardingOperand(use);
845+
if (isa<OwnershipForwardingMultipleValueInstruction>(user))
846+
return ForwardingOperand(use);
847+
return None;
848+
}
849+
850+
ValueOwnershipKind ForwardingOperand::getOwnershipKind() const {
851+
auto *user = use->getUser();
852+
if (auto *ofti = dyn_cast<OwnershipForwardingTermInst>(user))
853+
return ofti->getOwnershipKind();
854+
if (auto *ofsvi = dyn_cast<OwnershipForwardingSingleValueInst>(user))
855+
return ofsvi->getOwnershipKind();
856+
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(user))
857+
return ofci->getOwnershipKind();
858+
if (auto *ofseib = dyn_cast<OwnershipForwardingSelectEnumInstBase>(user))
859+
return ofseib->getOwnershipKind();
860+
if (auto *ofmvi = dyn_cast<OwnershipForwardingMultipleValueInstruction>(user))
861+
return ofmvi->getOwnershipKind();
862+
llvm_unreachable("Out of sync with ForwardingOperand::get?!");
863+
}
864+
865+
void ForwardingOperand::setOwnershipKind(ValueOwnershipKind newKind) const {
866+
auto *user = use->getUser();
867+
if (auto *ofsvi = dyn_cast<OwnershipForwardingSingleValueInst>(user))
868+
if (!ofsvi->getType().isTrivial(*ofsvi->getFunction()))
869+
return ofsvi->setOwnershipKind(newKind);
870+
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(user))
871+
if (!ofci->getType().isTrivial(*ofci->getFunction()))
872+
return ofci->setOwnershipKind(newKind);
873+
if (auto *ofseib = dyn_cast<OwnershipForwardingSelectEnumInstBase>(user))
874+
if (!ofseib->getType().isTrivial(*ofseib->getFunction()))
875+
return ofseib->setOwnershipKind(newKind);
876+
877+
if (auto *ofmvi = dyn_cast<OwnershipForwardingMultipleValueInstruction>(user)) {
878+
assert(ofmvi->getNumOperands() == 1);
879+
if (!ofmvi->getOperand(0)->getType().isTrivial(*ofmvi->getFunction())) {
880+
ofmvi->setOwnershipKind(newKind);
881+
// TODO: Refactor this better.
882+
if (auto *dsi = dyn_cast<DestructureStructInst>(ofmvi)) {
883+
for (auto &result : dsi->getAllResultsBuffer()) {
884+
if (result.getType().isTrivial(*dsi->getFunction()))
885+
continue;
886+
result.setOwnershipKind(newKind);
887+
}
888+
} else {
889+
auto *dti = cast<DestructureTupleInst>(ofmvi);
890+
for (auto &result : dti->getAllResultsBuffer()) {
891+
if (result.getType().isTrivial(*dti->getFunction()))
892+
continue;
893+
result.setOwnershipKind(newKind);
894+
}
895+
}
896+
}
897+
return;
898+
}
899+
900+
if (auto *ofti = dyn_cast<OwnershipForwardingTermInst>(user)) {
901+
assert(ofti->getNumOperands() == 1);
902+
if (!ofti->getOperand(0)->getType().isTrivial(*ofti->getFunction())) {
903+
ofti->setOwnershipKind(newKind);
904+
905+
// Then convert all of its incoming values that are owned to be guaranteed.
906+
for (auto &succ : ofti->getSuccessors()) {
907+
auto *succBlock = succ.getBB();
908+
909+
// If we do not have any arguments, then continue.
910+
if (succBlock->args_empty())
911+
continue;
912+
913+
for (auto *succArg : succBlock->getSILPhiArguments()) {
914+
// If we have an any value, just continue.
915+
if (!succArg->getType().isTrivial(*ofti->getFunction()))
916+
continue;
917+
succArg->setOwnershipKind(newKind);
918+
}
919+
}
920+
}
921+
return;
922+
}
923+
924+
llvm_unreachable("Out of sync with ForwardingOperand::get?!");
925+
}
926+
927+
void ForwardingOperand::replaceOwnershipKind(ValueOwnershipKind oldKind,
928+
ValueOwnershipKind newKind) const {
929+
auto *user = use->getUser();
930+
931+
if (auto *ofsvi = dyn_cast<OwnershipForwardingSingleValueInst>(user))
932+
if (ofsvi->getOwnershipKind() == oldKind)
933+
return ofsvi->setOwnershipKind(newKind);
934+
935+
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(user))
936+
if (ofci->getOwnershipKind() == oldKind)
937+
return ofci->setOwnershipKind(newKind);
938+
939+
if (auto *ofseib = dyn_cast<OwnershipForwardingSelectEnumInstBase>(user))
940+
if (ofseib->getOwnershipKind() == oldKind)
941+
return ofseib->setOwnershipKind(newKind);
942+
943+
if (auto *ofmvi = dyn_cast<OwnershipForwardingMultipleValueInstruction>(user)) {
944+
if (ofmvi->getOwnershipKind() == oldKind) {
945+
ofmvi->setOwnershipKind(newKind);
946+
}
947+
// TODO: Refactor this better.
948+
if (auto *dsi = dyn_cast<DestructureStructInst>(ofmvi)) {
949+
for (auto &result : dsi->getAllResultsBuffer()) {
950+
if (result.getOwnershipKind() != oldKind)
951+
continue;
952+
result.setOwnershipKind(newKind);
953+
}
954+
} else {
955+
auto *dti = cast<DestructureTupleInst>(ofmvi);
956+
for (auto &result : dti->getAllResultsBuffer()) {
957+
if (result.getOwnershipKind() != oldKind)
958+
continue;
959+
result.setOwnershipKind(newKind);
960+
}
961+
}
962+
return;
963+
}
964+
965+
if (auto *ofti = dyn_cast<OwnershipForwardingTermInst>(user)) {
966+
if (ofti->getOwnershipKind() == oldKind) {
967+
ofti->setOwnershipKind(newKind);
968+
// Then convert all of its incoming values that are owned to be guaranteed.
969+
for (auto &succ : ofti->getSuccessors()) {
970+
auto *succBlock = succ.getBB();
971+
972+
// If we do not have any arguments, then continue.
973+
if (succBlock->args_empty())
974+
continue;
975+
976+
for (auto *succArg : succBlock->getSILPhiArguments()) {
977+
// If we have an any value, just continue.
978+
if (succArg->getOwnershipKind() == oldKind) {
979+
succArg->setOwnershipKind(newKind);
980+
}
981+
}
982+
}
983+
}
984+
return;
985+
}
986+
llvm_unreachable("Out of sync with ForwardingOperand::get?!");
987+
}

lib/SILOptimizer/SemanticARC/OwnershipLiveRange.cpp

Lines changed: 4 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -224,81 +224,13 @@ void OwnershipLiveRange::insertEndBorrowsAtDestroys(
224224
}
225225
}
226226

227-
static void convertInstructionOwnership(SILInstruction *i,
228-
ValueOwnershipKind oldOwnership,
229-
ValueOwnershipKind newOwnership) {
230-
// If this is a term inst...
231-
if (auto *ti = dyn_cast<TermInst>(i)) {
232-
// First see if it is an ownership forwarding term inst. In such a case,
233-
// change the ownership kind as appropriate.
234-
if (auto *ofti = dyn_cast<OwnershipForwardingTermInst>(ti))
235-
if (ofti->getOwnershipKind() == oldOwnership)
236-
ofti->setOwnershipKind(newOwnership);
237-
238-
// Then convert all of its incoming values that are owned to be guaranteed.
239-
for (auto &succ : ti->getSuccessors()) {
240-
auto *succBlock = succ.getBB();
241-
242-
// If we do not have any arguments, then continue.
243-
if (succBlock->args_empty())
244-
continue;
245-
246-
for (auto *succArg : succBlock->getSILPhiArguments()) {
247-
// If we have an any value, just continue.
248-
if (succArg->getOwnershipKind() == oldOwnership) {
249-
succArg->setOwnershipKind(newOwnership);
250-
}
251-
}
252-
}
253-
return;
254-
}
255-
256-
assert(i->hasResults());
257-
for (SILValue result : i->getResults()) {
258-
if (auto *svi = dyn_cast<OwnershipForwardingSingleValueInst>(result)) {
259-
if (svi->getOwnershipKind() == oldOwnership) {
260-
svi->setOwnershipKind(newOwnership);
261-
}
262-
continue;
263-
}
264-
265-
if (auto *ofci = dyn_cast<OwnershipForwardingConversionInst>(result)) {
266-
if (ofci->getOwnershipKind() == oldOwnership) {
267-
ofci->setOwnershipKind(newOwnership);
268-
}
269-
continue;
270-
}
271-
272-
if (auto *sei = dyn_cast<OwnershipForwardingSelectEnumInstBase>(result)) {
273-
if (sei->getOwnershipKind() == oldOwnership) {
274-
sei->setOwnershipKind(newOwnership);
275-
}
276-
continue;
277-
}
278-
279-
if (auto *mvir = dyn_cast<MultipleValueInstructionResult>(result)) {
280-
if (mvir->getOwnershipKind() == oldOwnership) {
281-
mvir->setOwnershipKind(newOwnership);
282-
}
283-
if (auto *base = dyn_cast<OwnershipForwardingMultipleValueInstruction>(
284-
mvir->getParent())) {
285-
if (base->getOwnershipKind() == oldOwnership) {
286-
base->setOwnershipKind(newOwnership);
287-
}
288-
}
289-
continue;
290-
}
291-
292-
llvm_unreachable("unhandled forwarding instruction?!");
293-
}
294-
}
295-
296227
void OwnershipLiveRange::convertOwnedGeneralForwardingUsesToGuaranteed() && {
297228
while (!ownershipForwardingUses.empty()) {
298-
auto *i = ownershipForwardingUses.back()->getUser();
229+
auto *use = ownershipForwardingUses.back();
299230
ownershipForwardingUses = ownershipForwardingUses.drop_back();
300-
convertInstructionOwnership(i, ValueOwnershipKind::Owned,
301-
ValueOwnershipKind::Guaranteed);
231+
auto operand = *ForwardingOperand::get(use);
232+
operand.replaceOwnershipKind(ValueOwnershipKind::Owned,
233+
ValueOwnershipKind::Guaranteed);
302234
}
303235
}
304236

0 commit comments

Comments
 (0)