Skip to content

Commit 119d40d

Browse files
authored
Merge pull request #70705 from atrick/markdep-nonescaping
Add mark_dependence [nonescaping] flag.
2 parents dafcec6 + 264cbae commit 119d40d

28 files changed

+156
-51
lines changed

SwiftCompilerSources/Sources/SIL/Builder.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,4 +375,9 @@ public struct Builder {
375375
let endMutation = bridged.createEndCOWMutation(instance.bridged, keepUnique)
376376
return notifyNew(endMutation.getAs(EndCOWMutationInst.self))
377377
}
378+
379+
public func createMarkDependence(value: Value, base: Value, isNonEscaping: Bool) -> MarkDependenceInst {
380+
let markDependence = bridged.createMarkDependence(value.bridged, base.bridged, isNonEscaping)
381+
return notifyNew(markDependence.getAs(MarkDependenceInst.self))
382+
}
378383
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,13 @@ class GetAsyncContinuationInst : SingleValueInstruction {}
824824
final public
825825
class GetAsyncContinuationAddrInst : SingleValueInstruction, UnaryInstruction {}
826826

827-
828827
final public
829828
class MarkDependenceInst : SingleValueInstruction, ForwardingInstruction {
830829
public var valueOperand: Operand { operands[0] }
831830
public var baseOperand: Operand { operands[1] }
832831
public var value: Value { return valueOperand.value }
833832
public var base: Value { return baseOperand.value }
833+
public var isNonEscaping: Bool { bridged.MarkDependenceInst_isNonEscaping() }
834834
}
835835

836836
final public class RefToBridgeObjectInst : SingleValueInstruction, ForwardingInstruction {

docs/SIL.rst

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5503,24 +5503,35 @@ mark_dependence
55035503

55045504
::
55055505

5506-
sil-instruction :: 'mark_dependence' sil-operand 'on' sil-operand
5507-
5508-
%2 = mark_dependence %0 : $*T on %1 : $Builtin.NativeObject
5509-
5510-
Indicates that the validity of the first operand depends on the value
5511-
of the second operand. Operations that would destroy the second value
5512-
must not be moved before any instructions which depend on the result
5513-
of this instruction, exactly as if the address had been obviously
5514-
derived from that operand (e.g. using ``ref_element_addr``).
5515-
5516-
The result is always equal to the first operand. The first operand
5517-
will typically be an address, but it could be an address in a
5518-
non-obvious form, such as a Builtin.RawPointer or a struct containing
5519-
the same. Transformations should be somewhat forgiving here.
5520-
5521-
The second operand may have either object or address type. In the
5522-
latter case, the dependency is on the current value stored in the
5523-
address.
5506+
sil-instruction :: 'mark_dependence' '[nonescaping]'? sil-operand 'on' sil-operand
5507+
5508+
%2 = mark_dependence %value : $*T on %base : $Builtin.NativeObject
5509+
5510+
Indicates that the validity of ``%value`` depends on the value of
5511+
``%base``. Operations that would destroy ``%base`` must not be moved
5512+
before any instructions which depend on the result of this
5513+
instruction, exactly as if the address had been directly derived from
5514+
that operand (e.g. using ``ref_element_addr``).
5515+
5516+
The result is the forwarded value of ``%value``. ``%value`` may be an
5517+
address, but it could be an address in a non-obvious form, such as a
5518+
Builtin.RawPointer or a struct containing the same.
5519+
5520+
``%base`` may have either object or address type. In the latter case,
5521+
the dependency is on the current value stored in the address.
5522+
5523+
The optional ``nonescaping`` attribute indicates that no value derived
5524+
from ``%value`` escapes the lifetime of ``%base``. As with escaping
5525+
``mark_dependence``, all values transitively forwarded from ``%value``
5526+
must be destroyed within the lifetime of ``%base``. Unlike escaping
5527+
``mark_dependence``, this must be statically verifiable. Additionally,
5528+
unlike escaping ``mark_dependence``, derived values include copies of
5529+
``%value`` and values transitively forwarded from those copies. If
5530+
``%base`` is identical to ``%value`` this simply means that copies of
5531+
``%value`` do not outlive the original OSSA lifetime of
5532+
``%value``. Furthermore, unlike escaping ``mark_dependence``, no value
5533+
derived from ``%value`` may have a bitwise escape (conversion to
5534+
UnsafePointer) or pointer escape (unknown use).
55245535

55255536
is_unique
55265537
`````````

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ struct BridgedInstruction {
794794
BRIDGED_INLINE SwiftInt SwitchEnumInst_getCaseIndex(SwiftInt idx) const;
795795
BRIDGED_INLINE SwiftInt StoreInst_getStoreOwnership() const;
796796
BRIDGED_INLINE SwiftInt AssignInst_getAssignOwnership() const;
797+
BRIDGED_INLINE bool MarkDependenceInst_isNonEscaping() const;
797798
BRIDGED_INLINE AccessKind BeginAccessInst_getAccessKind() const;
798799
BRIDGED_INLINE bool BeginAccessInst_isStatic() const;
799800
BRIDGED_INLINE bool CopyAddrInst_isTakeOfSrc() const;
@@ -1118,6 +1119,7 @@ struct BridgedBuilder{
11181119
BridgedType::MetatypeRepresentation representation) const;
11191120
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createEndCOWMutation(BridgedValue instance,
11201121
bool keepUnique) const;
1122+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedInstruction createMarkDependence(BridgedValue value, BridgedValue base, bool isNonEscaping) const;
11211123
};
11221124

11231125
// Passmanager and Context

include/swift/SIL/SILBridgingImpl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,10 @@ SwiftInt BridgedInstruction::AssignInst_getAssignOwnership() const {
10401040
return (SwiftInt)getAs<swift::AssignInst>()->getOwnershipQualifier();
10411041
}
10421042

1043+
bool BridgedInstruction::MarkDependenceInst_isNonEscaping() const {
1044+
return getAs<swift::MarkDependenceInst>()->isNonEscaping();
1045+
}
1046+
10431047
BridgedInstruction::AccessKind BridgedInstruction::BeginAccessInst_getAccessKind() const {
10441048
return (AccessKind)getAs<swift::BeginAccessInst>()->getAccessKind();
10451049
}
@@ -1599,6 +1603,10 @@ BridgedInstruction BridgedBuilder::createEndCOWMutation(BridgedValue instance, b
15991603
keepUnique)};
16001604
}
16011605

1606+
BridgedInstruction BridgedBuilder::createMarkDependence(BridgedValue value, BridgedValue base, bool isNonEscaping) const {
1607+
return {unbridged().createMarkDependence(regularLoc(), value.getSILValue(), base.getSILValue(), isNonEscaping)};
1608+
}
1609+
16021610
SWIFT_END_NULLABILITY_ANNOTATIONS
16031611

16041612
#endif

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,15 +2284,18 @@ class SILBuilder {
22842284
SILValue value);
22852285

22862286
MarkDependenceInst *createMarkDependence(SILLocation Loc, SILValue value,
2287-
SILValue base) {
2288-
return createMarkDependence(Loc, value, base, value->getOwnershipKind());
2287+
SILValue base, bool isNonEscaping) {
2288+
return createMarkDependence(Loc, value, base, value->getOwnershipKind(),
2289+
isNonEscaping);
22892290
}
22902291

22912292
MarkDependenceInst *
22922293
createMarkDependence(SILLocation Loc, SILValue value, SILValue base,
2293-
ValueOwnershipKind forwardingOwnershipKind) {
2294+
ValueOwnershipKind forwardingOwnershipKind,
2295+
bool isNonEscaping) {
22942296
return insert(new (getModule()) MarkDependenceInst(
2295-
getSILDebugLocation(Loc), value, base, forwardingOwnershipKind));
2297+
getSILDebugLocation(Loc), value, base,
2298+
forwardingOwnershipKind, isNonEscaping));
22962299
}
22972300

22982301
IsUniqueInst *createIsUnique(SILLocation Loc, SILValue operand) {

include/swift/SIL/SILCloner.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,8 +2950,9 @@ void SILCloner<ImplClass>::visitMarkDependenceInst(MarkDependenceInst *Inst) {
29502950
getOpLocation(Inst->getLoc()), getOpValue(Inst->getValue()),
29512951
getOpValue(Inst->getBase()),
29522952
getBuilder().hasOwnership()
2953-
? Inst->getForwardingOwnershipKind()
2954-
: ValueOwnershipKind(OwnershipKind::None)));
2953+
? Inst->getForwardingOwnershipKind()
2954+
: ValueOwnershipKind(OwnershipKind::None),
2955+
/*isNonEscaping*/false));
29552956
}
29562957

29572958
template<typename ImplClass>

include/swift/SIL/SILInstruction.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8290,17 +8290,33 @@ class UncheckedOwnershipConversionInst
82908290
/// result) have a dependence on "base" being alive. Do not allow for things
82918291
/// that /may/ destroy base to be moved earlier than any of these uses of
82928292
/// "value"'.
8293+
///
8294+
/// The dependent 'value' may be marked 'nonescaping', which guarantees that the
8295+
/// lifetime dependence is statically enforceable. In this case, the compiler
8296+
/// must be able to follow all values forwarded from the dependent 'value', and
8297+
/// recognize all final (non-forwarded, non-escaping) use points. This implies
8298+
/// that `findPointerEscape` is false. A diagnostic pass checks that the
8299+
/// incoming SIL to verify that these use points are all initially within the
8300+
/// 'base' lifetime. Regular 'mark_dependence' semantics ensure that
8301+
/// optimizations cannot violate the lifetime dependence after diagnostics.
82938302
class MarkDependenceInst
82948303
: public InstructionBase<SILInstructionKind::MarkDependenceInst,
82958304
OwnershipForwardingSingleValueInstruction> {
82968305
friend SILBuilder;
82978306

82988307
FixedOperandList<2> Operands;
82998308

8309+
USE_SHARED_UINT8;
8310+
83008311
MarkDependenceInst(SILDebugLocation DebugLoc, SILValue value, SILValue base,
8301-
ValueOwnershipKind forwardingOwnershipKind)
8312+
ValueOwnershipKind forwardingOwnershipKind,
8313+
bool isNonEscaping)
83028314
: InstructionBase(DebugLoc, value->getType(), forwardingOwnershipKind),
8303-
Operands{this, value, base} {}
8315+
Operands{this, value, base} {
8316+
if (isNonEscaping) {
8317+
sharedUInt8().MarkDependenceInst.nonEscaping = true;
8318+
}
8319+
}
83048320

83058321
public:
83068322
enum { Value, Base };
@@ -8318,6 +8334,10 @@ class MarkDependenceInst
83188334

83198335
ArrayRef<Operand> getAllOperands() const { return Operands.asArray(); }
83208336
MutableArrayRef<Operand> getAllOperands() { return Operands.asArray(); }
8337+
8338+
bool isNonEscaping() const {
8339+
return sharedUInt8().MarkDependenceInst.nonEscaping;
8340+
}
83218341
};
83228342

83238343
/// Promote an Objective-C block that is on the stack to the heap, or simply

include/swift/SIL/SILNode.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ class alignas(8) SILNode :
276276
pointerEscape : 1,
277277
fromVarDecl : 1);
278278

279+
SHARED_FIELD(MarkDependenceInst, uint8_t
280+
nonEscaping : 1);
281+
279282
// Do not use `_sharedUInt8_private` outside of SILNode.
280283
} _sharedUInt8_private;
281284
// clang-format on

lib/IRGen/LoadableByAddress.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2840,7 +2840,8 @@ bool LoadableByAddress::recreateConvInstr(SILInstruction &I,
28402840
case SILInstructionKind::MarkDependenceInst: {
28412841
auto instr = cast<MarkDependenceInst>(convInstr);
28422842
newInstr = convBuilder.createMarkDependence(
2843-
instr->getLoc(), instr->getValue(), instr->getBase());
2843+
instr->getLoc(), instr->getValue(), instr->getBase(),
2844+
instr->isNonEscaping());
28442845
break;
28452846
}
28462847
case SILInstructionKind::DifferentiableFunctionInst: {

0 commit comments

Comments
 (0)