Skip to content

Commit 786eb94

Browse files
committed
Support @guaranteed forwarding phis
1 parent dfbb2bd commit 786eb94

30 files changed

+1058
-389
lines changed

include/swift/SIL/LinearLifetimeChecker.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class LinearLifetimeChecker {
5353
class ErrorBuilder;
5454

5555
private:
56-
friend class ReborrowVerifier;
56+
friend class GuaranteedPhiVerifier;
5757
friend class SILOwnershipVerifier;
5858
friend class SILValueOwnershipChecker;
5959

include/swift/SIL/OwnershipUtils.h

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,32 @@ inline bool isGuaranteedForwarding(SILValue value) {
9090
return canOpcodeForwardGuaranteedValues(value);
9191
}
9292

93+
/// Returns true if it is a forwarding phi
94+
inline bool isGuaranteedForwardingPhi(SILValue value) {
95+
if (value->getOwnershipKind() != OwnershipKind::Guaranteed) {
96+
return false;
97+
}
98+
if (isa<BeginBorrowInst>(value) || isa<LoadBorrowInst>(value)) {
99+
return false;
100+
}
101+
auto *phi = dyn_cast<SILPhiArgument>(value);
102+
if (!phi || !phi->isPhi()) {
103+
return true;
104+
}
105+
bool isGuaranteedForwardingPhi = true;
106+
phi->visitTransitiveIncomingPhiOperands(
107+
[&](auto *phi, auto *operand) -> bool {
108+
if (isa<BeginBorrowInst>(operand->get()) ||
109+
isa<LoadBorrowInst>(operand->get())) {
110+
isGuaranteedForwardingPhi = false;
111+
return false;
112+
}
113+
return true;
114+
});
115+
116+
return isGuaranteedForwardingPhi;
117+
}
118+
93119
/// Is the opcode that produces \p value capable of forwarding owned values?
94120
///
95121
/// This may be true even if the current instance of the instruction is not a
@@ -215,6 +241,11 @@ bool findExtendedTransitiveGuaranteedUses(
215241
bool findUsesOfSimpleValue(SILValue value,
216242
SmallVectorImpl<Operand *> *usePoints = nullptr);
217243

244+
/// Visit all GuaranteedForwardingPhis of \p value, not looking through
245+
/// reborrows.
246+
bool visitGuaranteedForwardingPhisForSSAValue(
247+
SILValue value, function_ref<bool(Operand *)> func);
248+
218249
/// An operand that forwards ownership to one or more results.
219250
class ForwardingOperand {
220251
Operand *use = nullptr;
@@ -1249,14 +1280,19 @@ OwnedValueIntroducer getSingleOwnedValueIntroducer(SILValue value);
12491280

12501281
using BaseValueSet = SmallPtrSet<SILValue, 8>;
12511282

1252-
/// Starting from \p initialScopeOperand, find all reborrows and their
1253-
/// corresponding base values, and run the visitor function \p
1254-
/// visitReborrowBaseValuePair on them.
1255-
/// Note that a reborrow phi, can have different base values based on different
1256-
/// control flow paths.
1257-
void findTransitiveReborrowBaseValuePairs(
1258-
BorrowingOperand initialScopeOperand, SILValue origBaseValue,
1259-
function_ref<void(SILPhiArgument *, SILValue)> visitReborrowBaseValuePair);
1283+
/// Starting from \p borrowInst, find all reborrows along with their base
1284+
/// values, and run the visitor function \p visitReborrowPhiBaseValuePair on
1285+
/// them.
1286+
void visitExtendedReborrowPhiBaseValuePairs(
1287+
BeginBorrowInst *borrowInst, function_ref<void(SILPhiArgument *, SILValue)>
1288+
visitReborrowPhiBaseValuePair);
1289+
1290+
/// Starting from \p borrow, find all GuaranteedForwardingPhi uses along with
1291+
/// their base values, and run the visitor function \p
1292+
/// visitGuaranteedForwardingPhiBaseValuePair on them.
1293+
void visitExtendedGuaranteedForwardingPhiBaseValuePairs(
1294+
BorrowedValue borrow, function_ref<void(SILPhiArgument *, SILValue)>
1295+
visitGuaranteedForwardingPhiBaseValuePair);
12601296

12611297
/// Visit the phis in the same block as \p phi which are reborrows of a borrow
12621298
/// of one of the values reaching \p phi.

include/swift/SIL/SILValue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,8 @@ struct OperandOwnership {
833833
/// borrow scope.
834834
/// (tuple_extract, struct_extract, cast, switch)
835835
GuaranteedForwarding,
836+
/// A GuaranteedForwarding value passed as a phi operand.
837+
GuaranteedForwardingPhi,
836838
/// End Borrow. End the borrow scope opened directly by the operand.
837839
/// The operand must be a begin_borrow, begin_apply, or function argument.
838840
/// (end_borrow, end_apply)
@@ -925,6 +927,7 @@ inline OwnershipConstraint OperandOwnership::getOwnershipConstraint() {
925927
return {OwnershipKind::Owned, UseLifetimeConstraint::LifetimeEnding};
926928
case OperandOwnership::InteriorPointer:
927929
case OperandOwnership::GuaranteedForwarding:
930+
case OperandOwnership::GuaranteedForwardingPhi:
928931
return {OwnershipKind::Guaranteed,
929932
UseLifetimeConstraint::NonLifetimeEnding};
930933
case OperandOwnership::EndBorrow:
@@ -953,6 +956,7 @@ inline bool canAcceptUnownedValue(OperandOwnership operandOwnership) {
953956
case OperandOwnership::ForwardingConsume:
954957
case OperandOwnership::InteriorPointer:
955958
case OperandOwnership::GuaranteedForwarding:
959+
case OperandOwnership::GuaranteedForwardingPhi:
956960
case OperandOwnership::EndBorrow:
957961
case OperandOwnership::Reborrow:
958962
return false;

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ bool swift::checkOperandOwnershipInvariants(const Operand *operand,
2727
// Must be a valid BorrowingOperand.
2828
return bool(BorrowingOperand(const_cast<Operand *>(operand)));
2929
}
30+
if (opOwnership == OperandOwnership::GuaranteedForwarding) {
31+
return canOpcodeForwardGuaranteedValues(const_cast<Operand *>(operand));
32+
}
3033
return true;
3134
}
3235

@@ -440,10 +443,10 @@ OperandOwnership OperandOwnershipClassifier::visitBranchInst(BranchInst *bi) {
440443
ValueOwnershipKind destBlockArgOwnershipKind =
441444
bi->getDestBB()->getArgument(getOperandIndex())->getOwnershipKind();
442445

443-
// FIXME: remove this special case once all aggregate operations behave just
444-
// like phis.
445446
if (destBlockArgOwnershipKind == OwnershipKind::Guaranteed) {
446-
return OperandOwnership::Reborrow;
447+
return isGuaranteedForwardingPhi(getValue())
448+
? OperandOwnership::GuaranteedForwardingPhi
449+
: OperandOwnership::Reborrow;
447450
}
448451
return destBlockArgOwnershipKind.getForwardingOperandOwnership(
449452
/*allowUnowned*/true);

lib/SIL/IR/SILValue.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,8 @@ StringRef OperandOwnership::asString() const {
432432
return "interior-pointer";
433433
case OperandOwnership::GuaranteedForwarding:
434434
return "guaranteed-forwarding";
435+
case OperandOwnership::GuaranteedForwardingPhi:
436+
return "guaranteed-forwarding-phi";
435437
case OperandOwnership::EndBorrow:
436438
return "end-borrow";
437439
case OperandOwnership::Reborrow:

0 commit comments

Comments
 (0)