Skip to content

Optimizer: re-implement and improve the AllocBoxToStack pass #82349

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jun 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d025e9f
SIL: add `var Argument.decl: ValueDecl?`
eeckstein Jun 18, 2025
094b246
SIL: `FunctionArgument.copyFlags` needs a MutatingContext argument
eeckstein Jun 18, 2025
1f304e5
SIL: improve APIs for `Box` types
eeckstein Jun 18, 2025
40363d8
Optimizer: fix the InstructionRange utility for control flow graphs w…
eeckstein Jun 18, 2025
f83fb1b
Optimizer: add `FunctionWorklist` and `CrossFunctionValueWorklist`
eeckstein Jun 18, 2025
57e08af
SIL: add `ApplySite.calleeArgument(of operand: Operand, in callee: Fu…
eeckstein Jun 18, 2025
4212c61
Optimizer: add `Context.createSpecializedFunctionDeclaration`
eeckstein Jun 18, 2025
63cb683
SIL: improve some `Location` APIs
eeckstein Jun 18, 2025
5b9c206
Optimizer: remove don't use `locationOfNextNonMetaInstruction` for ge…
eeckstein Jun 18, 2025
bc7024e
Optimizer: fix `ModulePassContext.mangle(withDeadArguments:)`
eeckstein Jun 18, 2025
de28cf0
Optimizer: add `Context. mangle(withBoxToStackPromotedArguments)`
eeckstein Jun 18, 2025
d8e4e50
Optimizer: add some SIL modification APIs to Context
eeckstein Jun 18, 2025
9bd85c6
SIL: add some `Function` APIs
eeckstein Jun 18, 2025
7deec66
Optimizer: add two utilities in OptUtils.swift
eeckstein Jun 18, 2025
28dd6f7
Optimizer: improve the `SpecializationCloner`
eeckstein Jun 18, 2025
c482b09
SIL: let `Builder.createAllocStack` specify a `debugVariable`
eeckstein Jun 18, 2025
c702982
SIL: fix debug locations for various kind of instructions
eeckstein Jun 18, 2025
c19aa69
SIL: implement `Function.isSerialized` and `Function.isAnySerialized`…
eeckstein Jun 18, 2025
2259fe6
SIL: add some instruction creation functions in Builder
eeckstein Jun 18, 2025
fc8f264
SIL: add some instruction APIs
eeckstein Jun 18, 2025
b256bab
fix `BridgedPassContext::addFunctionToPassManagerWorklist`
eeckstein Jun 18, 2025
f70177c
SIL: fix typo in comment in Function.swift
eeckstein Jun 18, 2025
fa56ba2
link SwiftCompilerSources modules to lldb-moduleimport-test and swift…
eeckstein Jun 18, 2025
6714a72
Optimizer: re-implement and improve the AllocBoxToStack pass
eeckstein Jun 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions SwiftCompilerSources/Sources/AST/Declarations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,9 @@ extension OptionalBridgedDeclObj {
public var decl: Decl? { obj.getAs(Decl.self) }
public func getAs<T: Decl>(_ declType: T.Type) -> T? { obj.getAs(T.self) }
}

extension Optional where Wrapped == Decl {
public var bridged: OptionalBridgedDeclObj {
OptionalBridgedDeclObj(self?.bridged.obj)
}
}
1 change: 1 addition & 0 deletions SwiftCompilerSources/Sources/AST/Type.swift
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ extension TypeProperties {
public var isMetatype: Bool { rawType.bridged.isMetatypeType() }
public var isExistentialMetatype: Bool { rawType.bridged.isExistentialMetatypeType() }
public var isDynamicSelf: Bool { rawType.bridged.isDynamicSelf()}
public var isBox: Bool { rawType.bridged.isBox() }

/// True if this is the type which represents an integer literal used in a type position.
/// For example `N` in `struct T<let N: Int> {}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,29 @@ struct BasicBlockRange : CustomStringConvertible, NoReflectionChildren {
}

/// Insert a potential end block.
mutating func insert(_ block: BasicBlock) {
///
/// Returns true if the begin-block is reached during backward propagation.
/// Usually this is not relevant, but InstructionRange needs this information.
@discardableResult
mutating func insert(_ block: BasicBlock) -> Bool {
if wasInserted.insert(block) {
inserted.append(block)
}
worklist.pushIfNotVisited(block)
var visitedBeginBlock = false
while let b = worklist.pop() {
inclusiveRange.append(b)
if b != begin {
for pred in b.predecessors {
if pred == begin {
visitedBeginBlock = true
}
worklist.pushIfNotVisited(pred)
inExclusiveRange.insert(pred)
}
}
}
return visitedBeginBlock
}

/// Insert a sequence of potential end blocks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ struct InstructionRange : CustomStringConvertible, NoReflectionChildren {
mutating func insert(_ inst: Instruction) {
insertedInsts.insert(inst)
insertIntoRange(instructions: ReverseInstructionList(first: inst.previous))
blockRange.insert(inst.parentBlock)
if inst.parentBlock != blockRange.begin {
if blockRange.insert(inst.parentBlock) {
// The first time an instruction is inserted in another block than the begin-block we need to insert
// instructions from the begin instruction to the end of the begin block.
// For subsequent insertions this is a no-op: `insertIntoRange` will return immediately because those
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,63 @@ extension InstructionWorklist {
}
}

/// A worklist for `Function`s.
struct FunctionWorklist {

// The current functions in the worklist.
private(set) var functions = Array<Function>()

// All functions which were ever pushed to the worklist.
private var pushedFunctions = Set<Function>()

mutating func pushIfNotVisited(_ function: Function) {
if pushedFunctions.insert(function).inserted {
functions.append(function)
}
}

mutating func pushIfNotVisited(contentsOf functions: [Function]) {
for f in functions {
pushIfNotVisited(f)
}
}

mutating func pop() -> Function? {
return functions.popLast()
}
}

/// Like `ValueWorklist`, but allows pushing `Value`s from different functions -
/// at the cost of a less efficient implementation.
struct CrossFunctionValueWorklist {

// The current values in the worklist.
private(set) var values = Array<Value>()

// All values which were ever pushed to the worklist.
private var pushedValues = Set<ObjectIdentifier>(minimumCapacity: 8)

init() {
values.reserveCapacity(8)
}

mutating func pop() -> Value? {
return values.popLast()
}

mutating func pushIfNotVisited(_ value: Value) {
if pushedValues.insert(ObjectIdentifier(value)).inserted {
values.append(value)
}
}

mutating func pushIfNotVisited<S: Sequence>(contentsOf values: S) where S.Element == Value {
for value in values {
pushIfNotVisited(value)
}
}

func hasBeenPushed(_ value: Value) -> Bool {
return pushedValues.contains(ObjectIdentifier(value))
}
}
Loading