Skip to content

Commit 6f55aa4

Browse files
committed
SIL: add the borrowed-from instruction.
It declares from which enclosing values a guaranteed phi argument is borrowed from.
1 parent 9212271 commit 6f55aa4

32 files changed

+291
-16
lines changed

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ public struct Builder {
182182
return notifyNew(bridged.createBeginBorrow(value.bridged).getAs(BeginBorrowInst.self))
183183
}
184184

185+
public func createBorrowedFrom(borrowedValue: Value, enclosingValues: [Value]) -> BorrowedFromInst {
186+
let bfi = enclosingValues.withBridgedValues { valuesRef in
187+
return bridged.createBorrowedFrom(borrowedValue.bridged, valuesRef)
188+
}
189+
return notifyNew(bfi.getAs(BorrowedFromInst.self))
190+
}
191+
185192
@discardableResult
186193
public func createEndBorrow(of beginBorrow: Value) -> EndBorrowInst {
187194
return notifyNew(bridged.createEndBorrow(beginBorrow.bridged).getAs(EndBorrowInst.self))

SwiftCompilerSources/Sources/SIL/ForwardingInstruction.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ extension DifferentiableFunctionInst {
137137
public var singleForwardedOperand: Operand? { nil }
138138
}
139139

140+
extension BorrowedFromInst {
141+
public var singleForwardedOperand: Operand? {
142+
return operands[0]
143+
}
144+
}
145+
140146
// -----------------------------------------------------------------------------
141147
// Instructions with a singleForwardedOperand and additional operands.
142148

@@ -286,3 +292,8 @@ extension TuplePackExtractInst {
286292
public var preservesRepresentation: Bool { true }
287293
public var canForwardOwnedValues: Bool { false }
288294
}
295+
296+
extension BorrowedFromInst {
297+
public var preservesRepresentation: Bool { true }
298+
public var canForwardOwnedValues: Bool { false }
299+
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,17 @@ final public class BeginBorrowInst : SingleValueInstruction, UnaryInstruction, B
985985
public var isFromVarDecl: Bool { bridged.BeginBorrow_isFromVarDecl() }
986986
}
987987

988+
final public class BorrowedFromInst : SingleValueInstruction, ForwardingInstruction, BorrowIntroducingInstruction {
989+
public var borrowedValue: Value { operands[0].value }
990+
public var enclosingOperands: OperandArray {
991+
let ops = operands
992+
return ops[1..<ops.count]
993+
}
994+
public var enclosingValues: LazyMapSequence<LazySequence<OperandArray>.Elements, Value> {
995+
enclosingOperands.values
996+
}
997+
}
998+
988999
final public class ProjectBoxInst : SingleValueInstruction, UnaryInstruction {
9891000
public var box: Value { operand.value }
9901001
public var fieldIndex: Int { bridged.ProjectBoxInst_fieldIndex() }

SwiftCompilerSources/Sources/SIL/Registration.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ public func registerSILClasses() {
169169
register(GetAsyncContinuationAddrInst.self)
170170
register(BeginAccessInst.self)
171171
register(BeginBorrowInst.self)
172+
register(BorrowedFromInst.self)
172173
register(ProjectBoxInst.self)
173174
register(CopyValueInst.self)
174175
register(ExplicitCopyValueInst.self)

docs/SIL.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4583,6 +4583,41 @@ We require that ``%1`` and ``%0`` have the same type ignoring SILValueCategory.
45834583

45844584
This instruction is only valid in functions in Ownership SSA form.
45854585

4586+
borrowed from
4587+
`````````````
4588+
4589+
::
4590+
4591+
sil-instruction ::= 'borrowed' sil-operand 'from' '(' (sil-operand (',' sil-operand)*)? ')'
4592+
4593+
bb1(%1 : @owned $T, %2 : @guaranteed $T):
4594+
%3 = borrowed %2 : $T from (%1 : $T, %0 : $S)
4595+
// %3 has type $T and guaranteed ownership
4596+
4597+
Declares from which enclosing values a guaranteed phi argument is borrowed
4598+
from.
4599+
An enclosing value is either a dominating borrow introducer (``%0``) of the
4600+
borrowed operand (``%2``) or an adjacent phi-argument in the same block
4601+
(``%1``).
4602+
In case of an adjacent phi, all incoming values of the adjacent phi must be
4603+
borrow introducers for the corresponding incoming value of the borrowed
4604+
operand in all predecessor blocks.
4605+
4606+
The borrowed operand (``%2``) is forwarded to the instruction result.
4607+
4608+
The list of enclosing values (operands after ``from``) can be empty if the
4609+
borrowed operand stems from a borrow introducer with no enclosing value, e.g.
4610+
a ``load_borrow``.
4611+
4612+
It is not strictly required that the borrowed operand is a phi argument, though
4613+
the instruction is only useful for phi arguments.
4614+
The borrowed operand can be any guaranteed value. This might be a result of
4615+
optimizations, for example, if CFG simplification merges blocks.
4616+
If the borrowed operand is a guaranteed phi, the phi must not have other uses
4617+
than the borrowed-from instruction.
4618+
4619+
This instruction is only valid in functions in Ownership SSA form.
4620+
45864621
end_lifetime
45874622
````````````
45884623

include/swift/SIL/InstWrappers.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,8 @@ class ForwardingOperation {
273273
&forwardingInst->getOperandRef(RefToBridgeObjectInst::ConvertedOperand);
274274
case SILInstructionKind::TuplePackExtractInst:
275275
return &forwardingInst->getOperandRef(TuplePackExtractInst::TupleOperand);
276+
case SILInstructionKind::BorrowedFromInst:
277+
return &forwardingInst->getOperandRef(0);
276278
default:
277279
int numRealOperands = forwardingInst->getNumRealOperands();
278280
if (numRealOperands == 0) {

include/swift/SIL/OwnershipUtils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,7 @@ class BorrowingOperandKind {
254254
enum Kind : uint8_t {
255255
Invalid = 0,
256256
BeginBorrow,
257+
BorrowedFrom,
257258
StoreBorrow,
258259
BeginApply,
259260
Branch,
@@ -279,6 +280,8 @@ class BorrowingOperandKind {
279280
return Kind::Invalid;
280281
case SILInstructionKind::BeginBorrowInst:
281282
return Kind::BeginBorrow;
283+
case SILInstructionKind::BorrowedFromInst:
284+
return Kind::BorrowedFrom;
282285
case SILInstructionKind::StoreBorrowInst:
283286
return Kind::StoreBorrow;
284287
case SILInstructionKind::BeginApplyInst:
@@ -392,6 +395,7 @@ struct BorrowingOperand {
392395
case BorrowingOperandKind::Invalid:
393396
llvm_unreachable("Using invalid case?!");
394397
case BorrowingOperandKind::BeginBorrow:
398+
case BorrowingOperandKind::BorrowedFrom:
395399
case BorrowingOperandKind::StoreBorrow:
396400
case BorrowingOperandKind::BeginApply:
397401
case BorrowingOperandKind::Apply:
@@ -424,6 +428,7 @@ struct BorrowingOperand {
424428
case BorrowingOperandKind::Invalid:
425429
llvm_unreachable("Using invalid case?!");
426430
case BorrowingOperandKind::BeginBorrow:
431+
case BorrowingOperandKind::BorrowedFrom:
427432
case BorrowingOperandKind::Branch:
428433
return true;
429434
case BorrowingOperandKind::StoreBorrow:

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,6 +1134,8 @@ struct BridgedBuilder{
11341134
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createFunctionRef(BridgedFunction function) const;
11351135
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createCopyValue(BridgedValue op) const;
11361136
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createBeginBorrow(BridgedValue op) const;
1137+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createBorrowedFrom(BridgedValue borrowedValue,
1138+
BridgedValueArray enclosingValues) const;
11371139
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createEndBorrow(BridgedValue op) const;
11381140
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createCopyAddr(BridgedValue from, BridgedValue to,
11391141
bool takeSource, bool initializeDest) const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,13 @@ BridgedInstruction BridgedBuilder::createBeginBorrow(BridgedValue op) const {
15051505
return {unbridged().createBeginBorrow(regularLoc(), op.getSILValue())};
15061506
}
15071507

1508+
BridgedInstruction BridgedBuilder::createBorrowedFrom(BridgedValue borrowedValue,
1509+
BridgedValueArray enclosingValues) const {
1510+
llvm::SmallVector<swift::SILValue, 16> evs;
1511+
return {unbridged().createBorrowedFrom(regularLoc(), borrowedValue.getSILValue(),
1512+
enclosingValues.getValues(evs))};
1513+
}
1514+
15081515
BridgedInstruction BridgedBuilder::createEndBorrow(BridgedValue op) const {
15091516
return {unbridged().createEndBorrow(regularLoc(), op.getSILValue())};
15101517
}

include/swift/SIL/SILBuilder.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,6 +823,12 @@ class SILBuilder {
823823
hasPointerEscape, fromVarDecl));
824824
}
825825

826+
BorrowedFromInst *createBorrowedFrom(SILLocation Loc, SILValue borrowedValue,
827+
ArrayRef<SILValue> enclosingValues) {
828+
return insert(BorrowedFromInst::create(getSILDebugLocation(Loc), borrowedValue,
829+
enclosingValues, getModule()));
830+
}
831+
826832
/// Convenience function for creating a load_borrow on non-trivial values and
827833
/// load [trivial] on trivial values. Becomes load unqualified in non-ossa
828834
/// functions.

include/swift/SIL/SILCloner.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,21 @@ void SILCloner<ImplClass>::visitBeginBorrowInst(BeginBorrowInst *Inst) {
12381238
Inst->hasPointerEscape(), Inst->isFromVarDecl()));
12391239
}
12401240

1241+
template <typename ImplClass>
1242+
void SILCloner<ImplClass>::visitBorrowedFromInst(BorrowedFromInst *bfi) {
1243+
getBuilder().setCurrentDebugScope(getOpScope(bfi->getDebugScope()));
1244+
if (!getBuilder().hasOwnership()) {
1245+
return recordFoldedValue(bfi, getOpValue(bfi->getBorrowedValue()));
1246+
}
1247+
1248+
auto enclosingValues = getOpValueArray<8>(bfi->getEnclosingValues());
1249+
recordClonedInstruction(bfi,
1250+
getBuilder().createBorrowedFrom(
1251+
getOpLocation(bfi->getLoc()),
1252+
getOpValue(bfi->getBorrowedValue()),
1253+
enclosingValues));
1254+
}
1255+
12411256
template <typename ImplClass>
12421257
void SILCloner<ImplClass>::visitStoreInst(StoreInst *Inst) {
12431258
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));

include/swift/SIL/SILInstruction.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4551,6 +4551,37 @@ class BeginBorrowInst
45514551
Operand *getSingleNonEndingUse() const;
45524552
};
45534553

4554+
/// BorrowedFromInst - Establishes borrow relations.
4555+
class BorrowedFromInst final : public InstructionBaseWithTrailingOperands<
4556+
SILInstructionKind::BorrowedFromInst, BorrowedFromInst,
4557+
OwnershipForwardingSingleValueInstruction> {
4558+
friend SILBuilder;
4559+
4560+
/// Because of the storage requirements of BorrowedFromInst, object
4561+
/// creation goes through 'create()'.
4562+
BorrowedFromInst(SILDebugLocation DebugLoc, ArrayRef<SILValue> operands);
4563+
4564+
/// Construct a BorrowedFromInst.
4565+
static BorrowedFromInst *create(SILDebugLocation DebugLoc, SILValue borrowedValue,
4566+
ArrayRef<SILValue> enclosingValues, SILModule &M);
4567+
4568+
public:
4569+
4570+
SILValue getBorrowedValue() {
4571+
return getAllOperands()[0].get();
4572+
}
4573+
4574+
/// The elements referenced by this StructInst.
4575+
ArrayRef<Operand> getEnclosingValueOperands() const {
4576+
return getAllOperands().drop_front();
4577+
}
4578+
4579+
/// The elements referenced by this StructInst.
4580+
OperandValueArrayRef getEnclosingValues() const {
4581+
return OperandValueArrayRef(getEnclosingValueOperands());
4582+
}
4583+
};
4584+
45544585
inline auto BeginBorrowInst::getEndBorrows() const -> EndBorrowRange {
45554586
return getUsersOfType<EndBorrowInst>();
45564587
}
@@ -10988,6 +11019,7 @@ OwnershipForwardingSingleValueInstruction::classof(SILInstructionKind kind) {
1098811019
case SILInstructionKind::BridgeObjectToRefInst:
1098911020
case SILInstructionKind::ThinToThickFunctionInst:
1099011021
case SILInstructionKind::UnconditionalCheckedCastInst:
11022+
case SILInstructionKind::BorrowedFromInst:
1099111023
return true;
1099211024
default:
1099311025
return false;

include/swift/SIL/SILNodes.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,8 @@ ABSTRACT_VALUE_AND_INST(SingleValueInstruction, ValueBase, SILInstruction)
543543
SingleValueInstruction, MayRead, DoesNotRelease)
544544
SINGLE_VALUE_INST(BeginBorrowInst, begin_borrow,
545545
SingleValueInstruction, MayHaveSideEffects, DoesNotRelease)
546+
SINGLE_VALUE_INST(BorrowedFromInst, borrowed,
547+
SingleValueInstruction, None, DoesNotRelease)
546548
SINGLE_VALUE_INST(StoreBorrowInst, store_borrow,
547549
SILInstruction, MayWrite, DoesNotRelease)
548550
// begin_access may trap. Trapping is unordered with respect to memory access,

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,9 @@ class IRGenSILFunction :
13141314
void visitBeginBorrowInst(BeginBorrowInst *i) {
13151315
llvm_unreachable("unimplemented");
13161316
}
1317+
void visitBorrowedFromInst(BorrowedFromInst *i) {
1318+
llvm_unreachable("unimplemented");
1319+
}
13171320
void visitEndBorrowInst(EndBorrowInst *i) {
13181321
llvm_unreachable("unimplemented");
13191322
}

lib/SIL/IR/OperandOwnership.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,12 @@ OperandOwnershipClassifier::visitBeginBorrowInst(BeginBorrowInst *borrow) {
420420
return OperandOwnership::Borrow;
421421
}
422422

423+
OperandOwnership
424+
OperandOwnershipClassifier::visitBorrowedFromInst(BorrowedFromInst *bfi) {
425+
return getOperandIndex() == 0 ? OperandOwnership::GuaranteedForwarding
426+
: OperandOwnership::InstantaneousUse;
427+
}
428+
423429
// MARK: Instructions whose use ownership depends on the operand in question.
424430

425431
OperandOwnership OperandOwnershipClassifier::

lib/SIL/IR/SILInstructions.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,6 +1472,24 @@ StructInst::StructInst(SILDebugLocation Loc, SILType Ty,
14721472
assert(!Ty.getStructOrBoundGenericStruct()->hasUnreferenceableStorage());
14731473
}
14741474

1475+
BorrowedFromInst *BorrowedFromInst::create(SILDebugLocation DebugLoc, SILValue borrowedValue,
1476+
ArrayRef<SILValue> enclosingValues, SILModule &M) {
1477+
auto Size = totalSizeToAlloc<swift::Operand>(enclosingValues.size() + 1);
1478+
auto Buffer = M.allocateInst(Size, alignof(StructInst));
1479+
SmallVector<SILValue, 8> operands;
1480+
operands.push_back(borrowedValue);
1481+
for (SILValue ev : enclosingValues) {
1482+
operands.push_back(ev);
1483+
}
1484+
return ::new (Buffer) BorrowedFromInst(DebugLoc, operands);
1485+
}
1486+
1487+
BorrowedFromInst::BorrowedFromInst(SILDebugLocation DebugLoc, ArrayRef<SILValue> operands)
1488+
: InstructionBaseWithTrailingOperands(operands, DebugLoc, operands[0]->getType(),
1489+
operands[0]->getOwnershipKind()) {
1490+
assert(operands[0]->getOwnershipKind() != OwnershipKind::Owned);
1491+
}
1492+
14751493
ObjectInst *ObjectInst::create(SILDebugLocation Loc, SILType Ty,
14761494
ArrayRef<SILValue> Elements,
14771495
unsigned NumBaseElements, SILModule &M,

lib/SIL/IR/SILPrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,6 +1732,20 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
17321732
*this << getIDAndType(BBI->getOperand());
17331733
}
17341734

1735+
void visitBorrowedFromInst(BorrowedFromInst *bfi) {
1736+
*this << getIDAndType(bfi->getBorrowedValue());
1737+
*this << " from (";
1738+
bool first = true;
1739+
for (SILValue ev : bfi->getEnclosingValues()) {
1740+
if (!first) {
1741+
*this << ", ";
1742+
}
1743+
first = false;
1744+
*this << getIDAndType(ev);
1745+
}
1746+
*this << ")";
1747+
}
1748+
17351749
void printStoreOwnershipQualifier(StoreOwnershipQualifier Qualifier) {
17361750
switch (Qualifier) {
17371751
case StoreOwnershipQualifier::Unqualified:

lib/SIL/IR/ValueOwnership.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ CONSTANT_OWNERSHIP_INST(Owned, WeakCopyValue)
7070
#include "swift/AST/ReferenceStorage.def"
7171

7272
CONSTANT_OWNERSHIP_INST(Guaranteed, BeginBorrow)
73+
CONSTANT_OWNERSHIP_INST(Guaranteed, BorrowedFrom)
7374
CONSTANT_OWNERSHIP_INST(Guaranteed, LoadBorrow)
7475
CONSTANT_OWNERSHIP_INST(None, GlobalValue)
7576
CONSTANT_OWNERSHIP_INST(Owned, AllocBox)

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3739,6 +3739,30 @@ bool SILParser::parseSpecificSILInstruction(SILBuilder &B,
37393739
break;
37403740
}
37413741

3742+
case SILInstructionKind::BorrowedFromInst: {
3743+
SILValue guaranteedValue;
3744+
if (parseTypedValueRef(guaranteedValue, B))
3745+
return true;
3746+
3747+
if (parseVerbatim("from") ||
3748+
P.parseToken(tok::l_paren, diag::expected_tok_in_sil_instr, "("))
3749+
return true;
3750+
3751+
if (P.Tok.isNot(tok::r_paren)) {
3752+
do {
3753+
if (parseTypedValueRef(Val, B))
3754+
return true;
3755+
OpList.push_back(Val);
3756+
} while (P.consumeIf(tok::comma));
3757+
}
3758+
if (P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")"))
3759+
return true;
3760+
3761+
ResultVal = B.createBorrowedFrom(InstLoc, guaranteedValue, OpList);
3762+
break;
3763+
}
3764+
3765+
37423766
#define NEVER_OR_SOMETIMES_LOADABLE_CHECKED_REF_STORAGE(Name, ...) \
37433767
case SILInstructionKind::Load##Name##Inst: { \
37443768
bool isTake = false; \

lib/SIL/Utils/InstructionUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType)
506506
case SILInstructionKind::LoadInst:
507507
case SILInstructionKind::LoadBorrowInst:
508508
case SILInstructionKind::BeginBorrowInst:
509+
case SILInstructionKind::BorrowedFromInst:
509510
case SILInstructionKind::StoreBorrowInst:
510511
case SILInstructionKind::MarkUninitializedInst:
511512
case SILInstructionKind::ProjectExistentialBoxInst:

0 commit comments

Comments
 (0)