Skip to content

Commit f3bcc8a

Browse files
committed
Support @guaranteed forwarding phis
1 parent e452912 commit f3bcc8a

30 files changed

+1067
-371
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: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,33 @@ 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+
isa<SILFunctionArgument>(value)) {
100+
return false;
101+
}
102+
auto *phi = dyn_cast<SILPhiArgument>(value);
103+
if (!phi || !phi->isPhi()) {
104+
return true;
105+
}
106+
bool isGuaranteedForwardingPhi = true;
107+
phi->visitTransitiveIncomingPhiOperands(
108+
[&](auto *phi, auto *operand) -> bool {
109+
if (isa<BeginBorrowInst>(operand->get()) ||
110+
isa<LoadBorrowInst>(operand->get())) {
111+
isGuaranteedForwardingPhi = false;
112+
return false;
113+
}
114+
return true;
115+
});
116+
117+
return isGuaranteedForwardingPhi;
118+
}
119+
93120
/// Is the opcode that produces \p value capable of forwarding owned values?
94121
///
95122
/// This may be true even if the current instance of the instruction is not a
@@ -215,6 +242,11 @@ bool findExtendedTransitiveGuaranteedUses(
215242
bool findUsesOfSimpleValue(SILValue value,
216243
SmallVectorImpl<Operand *> *usePoints = nullptr);
217244

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

12501282
using BaseValueSet = SmallPtrSet<SILValue, 8>;
12511283

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);
1284+
/// Starting from \p borrowInst, find all reborrows along with their base
1285+
/// values, and run the visitor function \p visitReborrowPhiBaseValuePair on
1286+
/// them.
1287+
void visitExtendedReborrowPhiBaseValuePairs(
1288+
BeginBorrowInst *borrowInst, function_ref<void(SILPhiArgument *, SILValue)>
1289+
visitReborrowPhiBaseValuePair);
1290+
1291+
/// Starting from \p borrow, find all GuaranteedForwardingPhi uses along with
1292+
/// their base values, and run the visitor function \p
1293+
/// visitGuaranteedForwardingPhiBaseValuePair on them.
1294+
void visitExtendedGuaranteedForwardingPhiBaseValuePairs(
1295+
BorrowedValue borrow, function_ref<void(SILPhiArgument *, SILValue)>
1296+
visitGuaranteedForwardingPhiBaseValuePair);
12601297

12611298
/// Visit the phis in the same block as \p phi which are reborrows of a borrow
12621299
/// 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
@@ -829,6 +829,8 @@ struct OperandOwnership {
829829
/// borrow scope.
830830
/// (tuple_extract, struct_extract, cast, switch)
831831
GuaranteedForwarding,
832+
/// A GuaranteedForwarding value passed as a phi operand.
833+
GuaranteedForwardingPhi,
832834
/// End Borrow. End the borrow scope opened directly by the operand.
833835
/// The operand must be a begin_borrow, begin_apply, or function argument.
834836
/// (end_borrow, end_apply)
@@ -923,6 +925,7 @@ inline OwnershipConstraint OperandOwnership::getOwnershipConstraint() {
923925
case OperandOwnership::GuaranteedForwarding:
924926
return {OwnershipKind::Guaranteed,
925927
UseLifetimeConstraint::NonLifetimeEnding};
928+
case OperandOwnership::GuaranteedForwardingPhi:
926929
case OperandOwnership::EndBorrow:
927930
case OperandOwnership::Reborrow:
928931
return {OwnershipKind::Guaranteed, UseLifetimeConstraint::LifetimeEnding};
@@ -949,6 +952,7 @@ inline bool canAcceptUnownedValue(OperandOwnership operandOwnership) {
949952
case OperandOwnership::ForwardingConsume:
950953
case OperandOwnership::InteriorPointer:
951954
case OperandOwnership::GuaranteedForwarding:
955+
case OperandOwnership::GuaranteedForwardingPhi:
952956
case OperandOwnership::EndBorrow:
953957
case OperandOwnership::Reborrow:
954958
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)