Skip to content

Commit ebc6b64

Browse files
committed
Support @guaranteed forwarding phis
1 parent 291878e commit ebc6b64

27 files changed

+955
-286
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: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,25 @@ inline bool isGuaranteedForwarding(SILValue value) {
9090
return canOpcodeForwardGuaranteedValues(value);
9191
}
9292

93+
/// Returns true if it is a forwarding phi
94+
inline bool isGuaranteedForwardingPhi(SILPhiArgument *phi) {
95+
if (phi->getOwnershipKind() != OwnershipKind::Guaranteed) {
96+
return false;
97+
}
98+
bool isGuaranteedForwardingPhi = true;
99+
phi->visitTransitiveIncomingPhiOperands(
100+
[&](auto *phi, auto *operand) -> bool {
101+
if (isa<BeginBorrowInst>(operand->get()) ||
102+
isa<LoadBorrowInst>(operand->get())) {
103+
isGuaranteedForwardingPhi = false;
104+
return false;
105+
}
106+
return true;
107+
});
108+
109+
return isGuaranteedForwardingPhi;
110+
}
111+
93112
/// Is the opcode that produces \p value capable of forwarding owned values?
94113
///
95114
/// This may be true even if the current instance of the instruction is not a
@@ -633,6 +652,21 @@ struct BorrowedValue {
633652
bool
634653
visitTransitiveLifetimeEndingUses(function_ref<bool(Operand *)> func) const;
635654

655+
/// Visit all GuaranteedForwarding operands of a borrow, not looking through
656+
/// reborrows.
657+
bool visitTransitiveGuaranteedForwardingUses(
658+
function_ref<bool(Operand *)> visitor) const;
659+
660+
/// Visit all GuaranteedForwardingPhi uses of a borrow, not looking through
661+
/// reborrows.
662+
bool visitTransitiveGuaranteedForwardingPhiUses(
663+
function_ref<bool(Operand *)> func) const;
664+
665+
/// Visit all GuaranteedForwardingPhi uses of a borrow, looking through
666+
/// reborrows.
667+
bool visitExtendedTransitiveGuaranteedForwardingPhiUses(
668+
function_ref<bool(Operand *)> func) const;
669+
636670
void print(llvm::raw_ostream &os) const;
637671
SWIFT_DEBUG_DUMP { print(llvm::dbgs()); }
638672

@@ -1249,14 +1283,19 @@ OwnedValueIntroducer getSingleOwnedValueIntroducer(SILValue value);
12491283

12501284
using BaseValueSet = SmallPtrSet<SILValue, 8>;
12511285

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

12611300
/// Visit the phis in the same block as \p phi which are reborrows of a borrow
12621301
/// 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: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -439,10 +439,19 @@ OperandOwnership OperandOwnershipClassifier::visitBranchInst(BranchInst *bi) {
439439
ValueOwnershipKind destBlockArgOwnershipKind =
440440
bi->getDestBB()->getArgument(getOperandIndex())->getOwnershipKind();
441441

442-
// FIXME: remove this special case once all aggregate operations behave just
443-
// like phis.
444442
if (destBlockArgOwnershipKind == OwnershipKind::Guaranteed) {
445-
return OperandOwnership::Reborrow;
443+
auto phiOp = getValue();
444+
if (isa<BeginBorrowInst>(phiOp) || isa<LoadBorrowInst>(phiOp)) {
445+
return OperandOwnership::Reborrow;
446+
}
447+
auto *arg = dyn_cast<SILPhiArgument>(phiOp);
448+
if (!arg || !arg->isPhi()) {
449+
return OperandOwnership::GuaranteedForwardingPhi;
450+
}
451+
452+
return isGuaranteedForwardingPhi(cast<SILPhiArgument>(phiOp))
453+
? OperandOwnership::GuaranteedForwardingPhi
454+
: OperandOwnership::Reborrow;
446455
}
447456
return destBlockArgOwnershipKind.getForwardingOperandOwnership(
448457
/*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)