Skip to content

Commit d97a8ce

Browse files
authored
Merge pull request #80223 from atrick/enable-addressable
LifetimeDependence: enable addressable dependencies
2 parents c69cb76 + 69cfe61 commit d97a8ce

File tree

16 files changed

+288
-26
lines changed

16 files changed

+288
-26
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceInsertion.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ extension LifetimeDependentApply {
138138
// for consistency, we use yieldAddress if any yielded value is an address.
139139
let targetKind = beginApply.yieldedValues.contains(where: { $0.type.isAddress })
140140
? TargetKind.yieldAddress : TargetKind.yield
141-
info.sources.push(LifetimeSource(targetKind: targetKind, convention: .scope(addressable: false),
141+
info.sources.push(LifetimeSource(targetKind: targetKind,
142+
convention: .scope(addressable: false, addressableForDeps: false),
142143
value: beginApply.token))
143144
}
144145
for operand in applySite.parameterOperands {
@@ -218,7 +219,7 @@ private extension LifetimeDependentApply.LifetimeSourceInfo {
218219
bases.append(source.value)
219220
case .result, .inParameter, .inoutParameter:
220221
// addressable dependencies directly depend on the incoming address.
221-
if context.options.enableAddressDependencies() && source.convention.isAddressable {
222+
if context.options.enableAddressDependencies() && source.convention.isAddressable(for: source.value) {
222223
bases.append(source.value)
223224
return
224225
}

SwiftCompilerSources/Sources/SIL/FunctionConvention.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ extension FunctionConvention {
237237

238238
public enum LifetimeDependenceConvention : CustomStringConvertible {
239239
case inherit
240-
case scope(addressable: Bool)
240+
case scope(addressable: Bool, addressableForDeps: Bool)
241241

242242
public var isScoped: Bool {
243243
switch self {
@@ -248,12 +248,12 @@ public enum LifetimeDependenceConvention : CustomStringConvertible {
248248
}
249249
}
250250

251-
public var isAddressable: Bool {
251+
public func isAddressable(for value: Value) -> Bool {
252252
switch self {
253253
case .inherit:
254254
return false
255-
case let .scope(addressable):
256-
return addressable
255+
case let .scope(addressable, addressableForDeps):
256+
return addressable || (addressableForDeps && value.type.isAddressableForDeps(in: value.parentFunction))
257257
}
258258
}
259259

@@ -313,7 +313,8 @@ extension FunctionConvention {
313313
}
314314
if scope {
315315
let addressable = bridged.checkAddressable(bridgedIndex(parameterIndex: index))
316-
return .scope(addressable: addressable)
316+
let addressableForDeps = bridged.checkConditionallyAddressable(bridgedIndex(parameterIndex: index))
317+
return .scope(addressable: addressable, addressableForDeps: addressableForDeps)
317318
}
318319
return nil
319320
}

SwiftCompilerSources/Sources/SIL/Type.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ public struct Type : TypeProperties, CustomStringConvertible, NoReflectionChildr
9292

9393
public var isMarkedAsImmortal: Bool { bridged.isMarkedAsImmortal() }
9494

95+
/// True if a value of this type can have its address taken by a lifetime-dependent value.
96+
public func isAddressableForDeps(in function: Function) -> Bool {
97+
bridged.isAddressableForDeps(function.bridged)
98+
}
99+
95100
//===--------------------------------------------------------------------===//
96101
// Properties of lowered `SILFunctionType`s
97102
//===--------------------------------------------------------------------===//

include/swift/AST/IndexSubset.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ class IndexSubset : public llvm::FoldingSetNode {
197197

198198
bool isSubsetOf(IndexSubset *other) const;
199199
bool isSupersetOf(IndexSubset *other) const;
200+
bool isDisjointWith(IndexSubset *other) const;
200201

201202
IndexSubset *adding(unsigned index, ASTContext &ctx) const;
202203
IndexSubset *extendingCapacity(ASTContext &ctx,

include/swift/AST/LifetimeDependence.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,10 @@ class LifetimeDependenceInfo {
250250
assert(!inheritLifetimeParamIndices ||
251251
!inheritLifetimeParamIndices->isEmpty());
252252
assert(!scopeLifetimeParamIndices || !scopeLifetimeParamIndices->isEmpty());
253-
assert((!conditionallyAddressableParamIndices
254-
|| (addressableParamIndices
255-
&& conditionallyAddressableParamIndices
256-
->isSubsetOf(addressableParamIndices)))
257-
&& "conditionally-addressable params not a subset of addressable params?");
253+
assert((!addressableParamIndices
254+
|| !conditionallyAddressableParamIndices
255+
|| conditionallyAddressableParamIndices->isDisjointWith(
256+
addressableParamIndices)));
258257
}
259258

260259
operator bool() const { return !empty(); }

include/swift/AST/SILOptions.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ class SILOptions {
333333

334334
/// Enable enforcement of lifetime dependencies on addressable arguments.
335335
/// Temporarily used to bootstrap the AddressableParameters feature.
336-
bool EnableAddressDependencies = false;
336+
bool EnableAddressDependencies = true;
337337

338338
SILOptions() {}
339339

include/swift/Option/FrontendOptions.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,6 +1505,9 @@ def platform_availability_inheritance_map_path
15051505
def enable_address_dependencies : Flag<["-"], "enable-address-dependencies">,
15061506
HelpText<"Enable enforcement of lifetime dependencies on addressable values.">;
15071507

1508+
def disable_address_dependencies : Flag<["-"], "disable-address-dependencies">,
1509+
HelpText<"Disable enforcement of lifetime dependencies on addressable values.">;
1510+
15081511
} // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]
15091512

15101513
def disable_experimental_parser_round_trip : Flag<["-"],

include/swift/SIL/SILBridging.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ struct BridgedLifetimeDependenceInfo {
159159
swift::IndexSubset *_Nullable inheritLifetimeParamIndices;
160160
swift::IndexSubset *_Nullable scopeLifetimeParamIndices;
161161
swift::IndexSubset *_Nullable addressableParamIndices;
162+
swift::IndexSubset *_Nullable conditionallyAddressableParamIndices;
162163
SwiftUInt targetIndex;
163164
bool immortal;
164165

@@ -168,6 +169,7 @@ struct BridgedLifetimeDependenceInfo {
168169
BRIDGED_INLINE bool checkInherit(SwiftInt index) const;
169170
BRIDGED_INLINE bool checkScope(SwiftInt index) const;
170171
BRIDGED_INLINE bool checkAddressable(SwiftInt index) const;
172+
BRIDGED_INLINE bool checkConditionallyAddressable(SwiftInt index) const;
171173
BRIDGED_INLINE SwiftInt getTargetIndex() const;
172174

173175
BRIDGED_INLINE BridgedOwnedString getDebugDescription() const;
@@ -259,6 +261,7 @@ struct BridgedType {
259261
BRIDGED_INLINE bool isExactSuperclassOf(BridgedType t) const;
260262
BRIDGED_INLINE bool isCalleeConsumedFunction() const;
261263
BRIDGED_INLINE bool isMarkedAsImmortal() const;
264+
BRIDGED_INLINE bool isAddressableForDeps(BridgedFunction f) const;
262265
BRIDGED_INLINE SwiftInt getCaseIdxOfEnumType(BridgedStringRef name) const;
263266
BRIDGED_INLINE SwiftInt getNumNominalFields() const;
264267
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getFieldType(SwiftInt idx, BridgedFunction f) const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ BridgedLifetimeDependenceInfo::BridgedLifetimeDependenceInfo(swift::LifetimeDepe
147147
: inheritLifetimeParamIndices(info.getInheritIndices()),
148148
scopeLifetimeParamIndices(info.getScopeIndices()),
149149
addressableParamIndices(info.getAddressableIndices()),
150+
conditionallyAddressableParamIndices(
151+
info.getConditionallyAddressableIndices()),
150152
targetIndex(info.getTargetIndex()), immortal(info.isImmortal()) {}
151153

152154
SwiftInt BridgedLifetimeDependenceInfoArray::count() const {
@@ -177,6 +179,12 @@ bool BridgedLifetimeDependenceInfo::checkAddressable(SwiftInt index) const {
177179
return addressableParamIndices && addressableParamIndices->contains(index);
178180
}
179181

182+
bool BridgedLifetimeDependenceInfo::
183+
checkConditionallyAddressable(SwiftInt index) const {
184+
return conditionallyAddressableParamIndices
185+
&& conditionallyAddressableParamIndices->contains(index);
186+
}
187+
180188
SwiftInt BridgedLifetimeDependenceInfo::getTargetIndex() const {
181189
return targetIndex;
182190
}
@@ -384,6 +392,10 @@ bool BridgedType::isMarkedAsImmortal() const {
384392
return unbridged().isMarkedAsImmortal();
385393
}
386394

395+
bool BridgedType::isAddressableForDeps(BridgedFunction f) const {
396+
return unbridged().isAddressableForDeps(*f.getFunction());
397+
}
398+
387399
SwiftInt BridgedType::getCaseIdxOfEnumType(BridgedStringRef name) const {
388400
return unbridged().getCaseIdxOfEnumType(name.unbridged());
389401
}

include/swift/SIL/SILType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -927,6 +927,10 @@ class SILType {
927927

928928
bool isMarkedAsImmortal() const;
929929

930+
/// True if a value of this type can have its address taken by a
931+
/// lifetime-dependent value.
932+
bool isAddressableForDeps(const SILFunction &function) const;
933+
930934
/// Returns true if this type is an actor type. Returns false if this is any
931935
/// other type. This includes distributed actors. To check for distributed
932936
/// actors and actors, use isAnyActor().

lib/AST/IndexSubset.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ bool IndexSubset::isSupersetOf(IndexSubset *other) const {
5252
return true;
5353
}
5454

55+
bool IndexSubset::isDisjointWith(IndexSubset *other) const {
56+
assert(capacity == other->capacity);
57+
for (auto index : range(numBitWords))
58+
if (getBitWord(index) & other->getBitWord(index))
59+
return false;
60+
return true;
61+
}
62+
5563
IndexSubset *IndexSubset::adding(unsigned index, ASTContext &ctx) const {
5664
assert(index < getCapacity());
5765
if (contains(index))

lib/AST/LifetimeDependence.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,9 @@ std::string LifetimeDependenceInfo::getString() const {
6363
}
6464
result += kind;
6565
if (addressable && addressable->contains(i)) {
66-
if (condAddressable && condAddressable->contains(i)) {
67-
result += "address_for_deps ";
68-
} else {
69-
result += "address ";
70-
}
66+
result += "address ";
67+
} else if (condAddressable && condAddressable->contains(i)) {
68+
result += "address_for_deps ";
7169
}
7270
result += std::to_string(i);
7371
isFirstSetBit = false;
@@ -1136,7 +1134,6 @@ static std::optional<LifetimeDependenceInfo> checkSILTypeModifiers(
11361134
break;
11371135
case LifetimeDescriptor::IsConditionallyAddressable:
11381136
conditionallyAddressableLifetimeParamIndices.set(index);
1139-
addressableLifetimeParamIndices.set(index);
11401137
break;
11411138
case LifetimeDescriptor::IsAddressable:
11421139
addressableLifetimeParamIndices.set(index);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3110,7 +3110,10 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
31103110
LTOKind.value() == IRGenLLVMLTOKind::None;
31113111

31123112

3113-
Opts.EnableAddressDependencies = Args.hasArg(OPT_enable_address_dependencies);
3113+
Opts.EnableAddressDependencies =
3114+
Args.hasFlag(OPT_enable_address_dependencies,
3115+
OPT_disable_address_dependencies,
3116+
Opts.EnableAddressDependencies);
31143117

31153118
return false;
31163119
}

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1823,14 +1823,12 @@ class DestructureInputs {
18231823
// is addressable-for-dependencies, then lower it with maximal abstraction
18241824
// as well.
18251825
auto &initialSubstTL = TC.getTypeLowering(origType, substType, expansion);
1826-
if (initialSubstTL.getRecursiveProperties().isAddressableForDependencies()) {
1826+
if (initialSubstTL.getRecursiveProperties()
1827+
.isAddressableForDependencies()) {
18271828
origType = AbstractionPattern::getOpaque();
18281829

1829-
// Remember that this lowered parameter is conditionally addressable in
1830-
// the addressable parameters vector.
1831-
AddressableLoweredParameters.resize(ParameterMap.size() + 1, false);
1832-
AddressableLoweredParameters[ParameterMap.size()] = true;
1833-
1830+
// Remember that this lowered parameter is conditionally
1831+
// addressable. Specialization may clear this flag.
18341832
ConditionallyAddressableLoweredParameters
18351833
.resize(ParameterMap.size() + 1, false);
18361834
ConditionallyAddressableLoweredParameters[ParameterMap.size()] = true;

lib/SIL/IR/SILType.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,6 +1148,13 @@ bool SILType::isMarkedAsImmortal() const {
11481148
return false;
11491149
}
11501150

1151+
bool SILType::isAddressableForDeps(const SILFunction &function) const {
1152+
auto contextType =
1153+
hasTypeParameter() ? function.mapTypeIntoContext(*this) : *this;
1154+
auto &tl = function.getTypeLowering(contextType);
1155+
return tl.getRecursiveProperties().isAddressableForDependencies();
1156+
}
1157+
11511158
intptr_t SILType::getFieldIdxOfNominalType(StringRef fieldName) const {
11521159
auto *nominal = getNominalOrBoundGenericNominal();
11531160
if (!nominal)

0 commit comments

Comments
 (0)