Skip to content

Commit 1d38956

Browse files
authored
Merge pull request #82349 from eeckstein/alloc-box-to-stack
Optimizer: re-implement and improve the AllocBoxToStack pass
2 parents aee16d7 + 6714a72 commit 1d38956

File tree

59 files changed

+1183
-328
lines changed

Some content is hidden

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

59 files changed

+1183
-328
lines changed

SwiftCompilerSources/Sources/AST/Declarations.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,9 @@ extension OptionalBridgedDeclObj {
157157
public var decl: Decl? { obj.getAs(Decl.self) }
158158
public func getAs<T: Decl>(_ declType: T.Type) -> T? { obj.getAs(T.self) }
159159
}
160+
161+
extension Optional where Wrapped == Decl {
162+
public var bridged: OptionalBridgedDeclObj {
163+
OptionalBridgedDeclObj(self?.bridged.obj)
164+
}
165+
}

SwiftCompilerSources/Sources/AST/Type.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ extension TypeProperties {
141141
public var isMetatype: Bool { rawType.bridged.isMetatypeType() }
142142
public var isExistentialMetatype: Bool { rawType.bridged.isExistentialMetatypeType() }
143143
public var isDynamicSelf: Bool { rawType.bridged.isDynamicSelf()}
144+
public var isBox: Bool { rawType.bridged.isBox() }
144145

145146
/// True if this is the type which represents an integer literal used in a type position.
146147
/// For example `N` in `struct T<let N: Int> {}`

SwiftCompilerSources/Sources/Optimizer/DataStructures/BasicBlockRange.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,29 @@ struct BasicBlockRange : CustomStringConvertible, NoReflectionChildren {
7777
}
7878

7979
/// Insert a potential end block.
80-
mutating func insert(_ block: BasicBlock) {
80+
///
81+
/// Returns true if the begin-block is reached during backward propagation.
82+
/// Usually this is not relevant, but InstructionRange needs this information.
83+
@discardableResult
84+
mutating func insert(_ block: BasicBlock) -> Bool {
8185
if wasInserted.insert(block) {
8286
inserted.append(block)
8387
}
8488
worklist.pushIfNotVisited(block)
89+
var visitedBeginBlock = false
8590
while let b = worklist.pop() {
8691
inclusiveRange.append(b)
8792
if b != begin {
8893
for pred in b.predecessors {
94+
if pred == begin {
95+
visitedBeginBlock = true
96+
}
8997
worklist.pushIfNotVisited(pred)
9098
inExclusiveRange.insert(pred)
9199
}
92100
}
93101
}
102+
return visitedBeginBlock
94103
}
95104

96105
/// Insert a sequence of potential end blocks.

SwiftCompilerSources/Sources/Optimizer/DataStructures/InstructionRange.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
8080
mutating func insert(_ inst: Instruction) {
8181
insertedInsts.insert(inst)
8282
insertIntoRange(instructions: ReverseInstructionList(first: inst.previous))
83-
blockRange.insert(inst.parentBlock)
84-
if inst.parentBlock != blockRange.begin {
83+
if blockRange.insert(inst.parentBlock) {
8584
// The first time an instruction is inserted in another block than the begin-block we need to insert
8685
// instructions from the begin instruction to the end of the begin block.
8786
// For subsequent insertions this is a no-op: `insertIntoRange` will return immediately because those

SwiftCompilerSources/Sources/Optimizer/DataStructures/Worklist.swift

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,63 @@ extension InstructionWorklist {
110110
}
111111
}
112112

113+
/// A worklist for `Function`s.
114+
struct FunctionWorklist {
115+
116+
// The current functions in the worklist.
117+
private(set) var functions = Array<Function>()
118+
119+
// All functions which were ever pushed to the worklist.
120+
private var pushedFunctions = Set<Function>()
121+
122+
mutating func pushIfNotVisited(_ function: Function) {
123+
if pushedFunctions.insert(function).inserted {
124+
functions.append(function)
125+
}
126+
}
127+
128+
mutating func pushIfNotVisited(contentsOf functions: [Function]) {
129+
for f in functions {
130+
pushIfNotVisited(f)
131+
}
132+
}
133+
134+
mutating func pop() -> Function? {
135+
return functions.popLast()
136+
}
137+
}
138+
139+
/// Like `ValueWorklist`, but allows pushing `Value`s from different functions -
140+
/// at the cost of a less efficient implementation.
141+
struct CrossFunctionValueWorklist {
142+
143+
// The current values in the worklist.
144+
private(set) var values = Array<Value>()
145+
146+
// All values which were ever pushed to the worklist.
147+
private var pushedValues = Set<ObjectIdentifier>(minimumCapacity: 8)
148+
149+
init() {
150+
values.reserveCapacity(8)
151+
}
152+
153+
mutating func pop() -> Value? {
154+
return values.popLast()
155+
}
156+
157+
mutating func pushIfNotVisited(_ value: Value) {
158+
if pushedValues.insert(ObjectIdentifier(value)).inserted {
159+
values.append(value)
160+
}
161+
}
162+
163+
mutating func pushIfNotVisited<S: Sequence>(contentsOf values: S) where S.Element == Value {
164+
for value in values {
165+
pushIfNotVisited(value)
166+
}
167+
}
168+
169+
func hasBeenPushed(_ value: Value) -> Bool {
170+
return pushedValues.contains(ObjectIdentifier(value))
171+
}
172+
}

0 commit comments

Comments
 (0)