Skip to content

Commit 360c5d8

Browse files
committed
Merge remote-tracking branch 'origin/main' into 20231019-merge-main
Conflicts: - `lib/AST/TypeCheckRequests.cpp` renamed `isMoveOnly` which requires a static_cast on rebranch because `Optional` is now a `std::optional`.
2 parents 9aa1772 + 251becb commit 360c5d8

File tree

158 files changed

+3267
-849
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

158 files changed

+3267
-849
lines changed

Diff for: SwiftCompilerSources/Sources/Optimizer/FunctionPasses/DeadStoreElimination.swift

+16-16
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ import SIL
5353
let deadStoreElimination = FunctionPass(name: "dead-store-elimination") {
5454
(function: Function, context: FunctionPassContext) in
5555

56+
// Avoid quadratic complexity by limiting the number of visited instructions.
57+
// This limit is sufficient for most "real-world" functions, by far.
58+
var complexityBudget = 10_000
59+
5660
for block in function.blocks {
5761

5862
// We cannot use for-in iteration here because if the store is split, the new
@@ -63,26 +67,26 @@ let deadStoreElimination = FunctionPass(name: "dead-store-elimination") {
6367
if !context.continueWithNextSubpassRun(for: store) {
6468
return
6569
}
66-
tryEliminate(store: store, context)
70+
tryEliminate(store: store, complexityBudget: &complexityBudget, context)
6771
}
6872
inst = i.next
6973
}
7074
}
7175
}
7276

73-
private func tryEliminate(store: StoreInst, _ context: FunctionPassContext) {
77+
private func tryEliminate(store: StoreInst, complexityBudget: inout Int, _ context: FunctionPassContext) {
7478
if !store.hasValidOwnershipForDeadStoreElimination {
7579
return
7680
}
7781

78-
switch store.isDead(context) {
82+
switch store.isDead(complexityBudget: &complexityBudget, context) {
7983
case .alive:
8084
break
8185
case .dead:
8286
context.erase(instruction: store)
8387
case .maybePartiallyDead(let subPath):
8488
// Check if the a partial store would really be dead to avoid unnecessary splitting.
85-
switch store.isDead(at: subPath, context) {
89+
switch store.isDead(at: subPath, complexityBudget: &complexityBudget, context) {
8690
case .alive, .maybePartiallyDead:
8791
break
8892
case .dead:
@@ -109,15 +113,15 @@ private extension StoreInst {
109113
}
110114
}
111115

112-
func isDead( _ context: FunctionPassContext) -> DataflowResult {
113-
return isDead(at: destination.accessPath, context)
116+
func isDead(complexityBudget: inout Int, _ context: FunctionPassContext) -> DataflowResult {
117+
return isDead(at: destination.accessPath, complexityBudget: &complexityBudget, context)
114118
}
115119

116-
func isDead(at accessPath: AccessPath, _ context: FunctionPassContext) -> DataflowResult {
120+
func isDead(at accessPath: AccessPath, complexityBudget: inout Int, _ context: FunctionPassContext) -> DataflowResult {
117121
var scanner = InstructionScanner(storePath: accessPath, storeAddress: self.destination, context.aliasAnalysis)
118122
let storageDefBlock = accessPath.base.reference?.referenceRoot.parentBlock
119123

120-
switch scanner.scan(instructions: InstructionList(first: self.next)) {
124+
switch scanner.scan(instructions: InstructionList(first: self.next), complexityBudget: &complexityBudget) {
121125
case .dead:
122126
return .dead
123127

@@ -145,7 +149,7 @@ private extension StoreInst {
145149
if let storageDefBlock = storageDefBlock, block == storageDefBlock {
146150
return DataflowResult(aliveWith: scanner.potentiallyDeadSubpath)
147151
}
148-
switch scanner.scan(instructions: block.instructions) {
152+
switch scanner.scan(instructions: block.instructions, complexityBudget: &complexityBudget) {
149153
case .transparent:
150154
worklist.pushIfNotVisited(contentsOf: block.successors)
151155
case .dead:
@@ -177,10 +181,6 @@ private struct InstructionScanner {
177181

178182
private(set) var potentiallyDeadSubpath: AccessPath? = nil
179183

180-
// Avoid quadratic complexity by limiting the number of visited instructions for each store.
181-
// The limit of 1000 instructions is not reached by far in "real-world" functions.
182-
private var budget = 1000
183-
184184
init(storePath: AccessPath, storeAddress: Value, _ aliasAnalysis: AliasAnalysis) {
185185
self.storePath = storePath
186186
self.storeAddress = storeAddress
@@ -193,7 +193,7 @@ private struct InstructionScanner {
193193
case transparent
194194
}
195195

196-
mutating func scan(instructions: InstructionList) -> Result {
196+
mutating func scan(instructions: InstructionList, complexityBudget: inout Int) -> Result {
197197
for inst in instructions {
198198
switch inst {
199199
case let successiveStore as StoreInst:
@@ -226,8 +226,8 @@ private struct InstructionScanner {
226226
}
227227
fallthrough
228228
default:
229-
budget -= 1
230-
if budget == 0 {
229+
complexityBudget -= 1
230+
if complexityBudget <= 0 {
231231
return .alive
232232
}
233233
if inst.mayRead(fromAddress: storeAddress, aliasAnalysis) {

Diff for: SwiftCompilerSources/Sources/Optimizer/FunctionPasses/RedundantLoadElimination.swift

+31-19
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ let earlyRedundantLoadElimination = FunctionPass(name: "early-redundant-load-eli
7474
}
7575

7676
private func eliminateRedundantLoads(in function: Function, ignoreArrays: Bool, _ context: FunctionPassContext) {
77+
78+
// Avoid quadratic complexity by limiting the number of visited instructions.
79+
// This limit is sufficient for most "real-world" functions, by far.
80+
var complexityBudget = 50_000
81+
7782
for block in function.blocks.reversed() {
7883

7984
// We cannot use for-in iteration here because if the load is split, the new
@@ -89,21 +94,21 @@ private func eliminateRedundantLoads(in function: Function, ignoreArrays: Bool,
8994
if ignoreArrays && load.type.isNominal && load.type.nominal == context.swiftArrayDecl {
9095
continue
9196
}
92-
tryEliminate(load: load, context)
97+
tryEliminate(load: load, complexityBudget: &complexityBudget, context)
9398
}
9499
}
95100
}
96101
}
97102

98-
private func tryEliminate(load: LoadInst, _ context: FunctionPassContext) {
99-
switch load.isRedundant(context) {
103+
private func tryEliminate(load: LoadInst, complexityBudget: inout Int, _ context: FunctionPassContext) {
104+
switch load.isRedundant(complexityBudget: &complexityBudget, context) {
100105
case .notRedundant:
101106
break
102107
case .redundant(let availableValues):
103108
replace(load: load, with: availableValues, context)
104109
case .maybePartiallyRedundant(let subPath):
105110
// Check if the a partial load would really be redundant to avoid unnecessary splitting.
106-
switch load.isRedundant(at: subPath, context) {
111+
switch load.isRedundant(at: subPath, complexityBudget: &complexityBudget, context) {
107112
case .notRedundant, .maybePartiallyRedundant:
108113
break
109114
case .redundant:
@@ -130,25 +135,29 @@ private extension LoadInst {
130135
}
131136
}
132137

133-
func isRedundant(_ context: FunctionPassContext) -> DataflowResult {
134-
return isRedundant(at: address.accessPath, context)
138+
func isRedundant(complexityBudget: inout Int, _ context: FunctionPassContext) -> DataflowResult {
139+
return isRedundant(at: address.accessPath, complexityBudget: &complexityBudget, context)
135140
}
136141

137-
func isRedundant(at accessPath: AccessPath, _ context: FunctionPassContext) -> DataflowResult {
142+
func isRedundant(at accessPath: AccessPath, complexityBudget: inout Int, _ context: FunctionPassContext) -> DataflowResult {
138143
var scanner = InstructionScanner(load: self, accessPath: accessPath, context.aliasAnalysis)
139144

140-
switch scanner.scan(instructions: ReverseInstructionList(first: self.previous), in: parentBlock) {
145+
switch scanner.scan(instructions: ReverseInstructionList(first: self.previous),
146+
in: parentBlock,
147+
complexityBudget: &complexityBudget)
148+
{
141149
case .overwritten:
142150
return DataflowResult(notRedundantWith: scanner.potentiallyRedundantSubpath)
143151
case .available:
144152
return .redundant(scanner.availableValues)
145153
case .transparent:
146-
return self.isRedundantInPredecessorBlocks(scanner: &scanner, context)
154+
return self.isRedundantInPredecessorBlocks(scanner: &scanner, complexityBudget: &complexityBudget, context)
147155
}
148156
}
149157

150158
private func isRedundantInPredecessorBlocks(
151159
scanner: inout InstructionScanner,
160+
complexityBudget: inout Int,
152161
_ context: FunctionPassContext
153162
) -> DataflowResult {
154163

@@ -157,7 +166,10 @@ private extension LoadInst {
157166
liferange.pushPredecessors(of: self.parentBlock)
158167

159168
while let block = liferange.pop() {
160-
switch scanner.scan(instructions: block.instructions.reversed(), in: block) {
169+
switch scanner.scan(instructions: block.instructions.reversed(),
170+
in: block,
171+
complexityBudget: &complexityBudget)
172+
{
161173
case .overwritten:
162174
return DataflowResult(notRedundantWith: scanner.potentiallyRedundantSubpath)
163175
case .available:
@@ -402,10 +414,6 @@ private struct InstructionScanner {
402414
private(set) var potentiallyRedundantSubpath: AccessPath? = nil
403415
private(set) var availableValues = Array<AvailableValue>()
404416

405-
// Avoid quadratic complexity by limiting the number of visited instructions for each store.
406-
// The limit of 1000 instructions is not reached by far in "real-world" functions.
407-
private var budget = 1000
408-
409417
init(load: LoadInst, accessPath: AccessPath, _ aliasAnalysis: AliasAnalysis) {
410418
self.load = load
411419
self.accessPath = accessPath
@@ -419,8 +427,16 @@ private struct InstructionScanner {
419427
case transparent
420428
}
421429

422-
mutating func scan(instructions: ReverseInstructionList, in block: BasicBlock) -> ScanResult {
430+
mutating func scan(instructions: ReverseInstructionList,
431+
in block: BasicBlock,
432+
complexityBudget: inout Int) -> ScanResult
433+
{
423434
for inst in instructions {
435+
complexityBudget -= 1
436+
if complexityBudget <= 0 {
437+
return .overwritten
438+
}
439+
424440
switch visit(instruction: inst) {
425441
case .available: return .available
426442
case .overwritten: return .overwritten
@@ -490,10 +506,6 @@ private struct InstructionScanner {
490506
default:
491507
break
492508
}
493-
budget -= 1
494-
if budget == 0 {
495-
return .overwritten
496-
}
497509
if load.loadOwnership == .take {
498510
// In case of `take`, don't allow reading instructions in the liferange.
499511
// Otherwise we cannot shrink the memory liferange afterwards.

Diff for: SwiftCompilerSources/Sources/SIL/Function.swift

+4
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
116116
}
117117
}
118118

119+
public var hasUnsafeNonEscapableResult: Bool {
120+
return bridged.hasUnsafeNonEscapableResult()
121+
}
122+
119123
/// True if the callee function is annotated with @_semantics("programtermination_point").
120124
/// This means that the function terminates the program.
121125
public var isProgramTerminationPoint: Bool { hasSemanticsAttribute("programtermination_point") }

Diff for: SwiftCompilerSources/Sources/SIL/Type.swift

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public struct Type : CustomStringConvertible, NoReflectionChildren {
5858
public var isMetatype: Bool { bridged.isMetatype() }
5959
public var isNoEscapeFunction: Bool { bridged.isNoEscapeFunction() }
6060
public var isAsyncFunction: Bool { bridged.isAsyncFunction() }
61+
public var isEscapable: Bool { bridged.isEscapable() }
6162

6263
public var canBeClass: BridgedType.TraitResult { bridged.canBeClass() }
6364

Diff for: cmake/caches/Windows-x86_64.cmake

+1
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ set(SWIFT_INSTALL_COMPONENTS
152152
sourcekit-inproc
153153
swift-remote-mirror
154154
swift-remote-mirror-headers
155+
swift-syntax-lib
155156
CACHE STRING "")
156157

157158
set(LLVM_DISTRIBUTION_COMPONENTS

Diff for: docs/ReferenceGuides/UnderscoredAttributes.md

+9
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,15 @@ This is the default behavior, unless the type annotated is an aggregate that
625625
consists entirely of `@_eagerMove` or trivial values, in which case the
626626
attribute overrides the inferred type-level annotation.
627627

628+
## `@_nonEscapable`
629+
630+
Indicates that a type is non-escapable. All instances of this type are
631+
non-escaping values. A non-escaping value's lifetime must be confined
632+
to another "parent" lifetime.
633+
634+
This is temporary until ~Escapable syntax is supported, which will
635+
also work as a generic type constraint.
636+
628637
## `@_marker`
629638

630639
Indicates that a protocol is a marker protocol. Marker protocols represent some

Diff for: include/swift-c/DependencyScan/DependencyScan.h

+4
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ SWIFTSCAN_PUBLIC swiftscan_string_ref_t
180180
swiftscan_swift_binary_detail_get_module_source_info_path(
181181
swiftscan_module_details_t details);
182182

183+
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
184+
swiftscan_swift_binary_detail_get_swift_overlay_dependencies(
185+
swiftscan_module_details_t details);
186+
183187
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
184188
swiftscan_swift_binary_detail_get_header_dependencies(
185189
swiftscan_module_details_t details);

Diff for: include/swift/AST/Attr.def

+6
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,12 @@ DECL_ATTR(_rawLayout, RawLayout,
423423
DECL_ATTR(_extern, Extern,
424424
OnFunc | ABIStableToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
425425
147)
426+
SIMPLE_DECL_ATTR(_nonEscapable, NonEscapable,
427+
OnNominalType | UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIBreakingToAdd | APIStableToRemove,
428+
148)
429+
SIMPLE_DECL_ATTR(_unsafeNonEscapableResult, UnsafeNonEscapableResult,
430+
OnAbstractFunction | OnSubscript | UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIBreakingToAdd | APIBreakingToRemove,
431+
149)
426432
CONTEXTUAL_SIMPLE_DECL_ATTR(final, Final,
427433
OnClass | OnFunc | OnAccessor | OnVar | OnSubscript | DeclModifier | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove,
428434
2)

Diff for: include/swift/AST/Decl.h

+32-7
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,9 @@ class InheritedTypes {
15961596
size_t size() const { return Entries.size(); }
15971597
IntRange<size_t> const getIndices() { return indices(Entries); }
15981598

1599+
/// Returns the ASTContext associated with the wrapped declaration.
1600+
ASTContext &getASTContext() const;
1601+
15991602
/// Returns the `TypeRepr *` for the entry of the inheritance clause at the
16001603
/// given index.
16011604
TypeRepr *getTypeRepr(unsigned i) const { return Entries[i].getTypeRepr(); }
@@ -1615,6 +1618,10 @@ class InheritedTypes {
16151618
/// NOTE: The `Type` associated with the entry may not be resolved yet.
16161619
const InheritedEntry &getEntry(unsigned i) const { return Entries[i]; }
16171620

1621+
// Retrieve the location of the colon character introducing the inheritance
1622+
// clause.
1623+
SourceLoc getColonLoc() const;
1624+
16181625
/// Returns the source location of the beginning of the inheritance clause.
16191626
SourceLoc getStartLoc() const {
16201627
return getEntries().front().getSourceRange().Start;
@@ -1624,6 +1631,10 @@ class InheritedTypes {
16241631
SourceLoc getEndLoc() const {
16251632
return getEntries().back().getSourceRange().End;
16261633
}
1634+
1635+
/// Compute the SourceRange to be used when removing entry \c i from the
1636+
/// inheritance clause. Accounts for commas and colons as-needed.
1637+
SourceRange getRemovalRange(unsigned i) const;
16271638
};
16281639

16291640
/// ExtensionDecl - This represents a type extension containing methods
@@ -2606,18 +2617,18 @@ class ValueDecl : public Decl {
26062617
/// optional result.
26072618
unsigned isIUO : 1;
26082619

2609-
/// Whether the "isMoveOnly" bit has been computed yet.
2610-
unsigned isMoveOnlyComputed : 1;
2620+
/// Whether the "isEscapable" bit has been computed yet.
2621+
unsigned isEscapable : 1;
26112622

2612-
/// Whether this declaration can not be copied and thus is move only.
2613-
unsigned isMoveOnly : 1;
2623+
/// Whether this declaration is escapable.
2624+
unsigned isEscapableComputed : 1;
26142625
} LazySemanticInfo = { };
26152626

26162627
friend class DynamicallyReplacedDeclRequest;
26172628
friend class OverriddenDeclsRequest;
26182629
friend class IsObjCRequest;
26192630
friend class IsFinalRequest;
2620-
friend class IsMoveOnlyRequest;
2631+
friend class IsEscapableRequest;
26212632
friend class IsDynamicRequest;
26222633
friend class IsImplicitlyUnwrappedOptionalRequest;
26232634
friend class InterfaceTypeRequest;
@@ -2920,8 +2931,8 @@ class ValueDecl : public Decl {
29202931
/// Is this declaration 'final'?
29212932
bool isFinal() const;
29222933

2923-
/// Is this declaration 'moveOnly'?
2924-
bool isMoveOnly() const;
2934+
/// Is this declaration escapable?
2935+
bool isEscapable() const;
29252936

29262937
/// Is this declaration marked with 'dynamic'?
29272938
bool isDynamic() const;
@@ -3095,8 +3106,18 @@ class ValueDecl : public Decl {
30953106

30963107
/// This is a common base class for declarations which declare a type.
30973108
class TypeDecl : public ValueDecl {
3109+
private:
30983110
ArrayRef<InheritedEntry> Inherited;
30993111

3112+
struct {
3113+
/// Whether the "hasNoncopyableAnnotation" bit has been computed yet.
3114+
unsigned isNoncopyableAnnotationComputed : 1;
3115+
3116+
/// Whether this declaration had a noncopyable inverse written somewhere.
3117+
unsigned hasNoncopyableAnnotation : 1;
3118+
} LazySemanticInfo = { };
3119+
friend class HasNoncopyableAnnotationRequest;
3120+
31003121
protected:
31013122
TypeDecl(DeclKind K, llvm::PointerUnion<DeclContext *, ASTContext *> context,
31023123
Identifier name, SourceLoc NameLoc,
@@ -3124,6 +3145,10 @@ class TypeDecl : public ValueDecl {
31243145

31253146
void setInherited(ArrayRef<InheritedEntry> i) { Inherited = i; }
31263147

3148+
/// Is this type _always_ noncopyable? Will answer 'false' if the type is
3149+
/// conditionally copyable.
3150+
bool isNoncopyable() const;
3151+
31273152
static bool classof(const Decl *D) {
31283153
return D->getKind() >= DeclKind::First_TypeDecl &&
31293154
D->getKind() <= DeclKind::Last_TypeDecl;

0 commit comments

Comments
 (0)