-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #65764 from eeckstein/globalopt
Rework optimization of global variables
- Loading branch information
Showing
89 changed files
with
1,745 additions
and
1,609 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
135 changes: 135 additions & 0 deletions
135
SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//===--- InitializeStaticGlobals.swift -------------------------------------==// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import SIL | ||
|
||
/// Converts a lazily initialized global to a statically initialized global variable. | ||
/// | ||
/// When this pass runs on a global initializer `[global_init_once_fn]` it tries to | ||
/// create a static initializer for the initialized global. | ||
/// | ||
/// ``` | ||
/// sil [global_init_once_fn] @globalinit { | ||
/// alloc_global @the_global | ||
/// %a = global_addr @the_global | ||
/// %i = some_const_initializer_insts | ||
/// store %i to %a | ||
/// } | ||
/// ``` | ||
/// The pass creates a static initializer for the global: | ||
/// ``` | ||
/// sil_global @the_global = { | ||
/// %initval = some_const_initializer_insts | ||
/// } | ||
/// ``` | ||
/// and removes the allocation and store instructions from the initializer function: | ||
/// ``` | ||
/// sil [global_init_once_fn] @globalinit { | ||
/// %a = global_addr @the_global | ||
/// %i = some_const_initializer_insts | ||
/// } | ||
/// ``` | ||
/// The initializer then becomes a side-effect free function which let's the builtin- | ||
/// simplification remove the `builtin "once"` which calls the initializer. | ||
/// | ||
let initializeStaticGlobalsPass = FunctionPass(name: "initialize-static-globals") { | ||
(function: Function, context: FunctionPassContext) in | ||
|
||
if !function.isGlobalInitOnceFunction { | ||
return | ||
} | ||
|
||
guard let (allocInst, storeToGlobal) = function.getGlobalInitialization() else { | ||
return | ||
} | ||
|
||
if !allocInst.global.canBeInitializedStatically { | ||
return | ||
} | ||
|
||
context.createStaticInitializer(for: allocInst.global, | ||
initValue: storeToGlobal.source as! SingleValueInstruction) | ||
context.erase(instruction: allocInst) | ||
context.erase(instruction: storeToGlobal) | ||
} | ||
|
||
private extension Function { | ||
/// Analyses the global initializer function and returns the `alloc_global` and `store` | ||
/// instructions which initialize the global. | ||
/// | ||
/// The function's single basic block must contain following code pattern: | ||
/// ``` | ||
/// alloc_global @the_global | ||
/// %a = global_addr @the_global | ||
/// %i = some_const_initializer_insts | ||
/// store %i to %a | ||
/// ``` | ||
func getGlobalInitialization() -> (allocInst: AllocGlobalInst, storeToGlobal: StoreInst)? { | ||
|
||
guard let block = singleBlock else { | ||
return nil | ||
} | ||
|
||
var allocInst: AllocGlobalInst? = nil | ||
var globalAddr: GlobalAddrInst? = nil | ||
var store: StoreInst? = nil | ||
|
||
for inst in block.instructions { | ||
switch inst { | ||
case is ReturnInst, | ||
is DebugValueInst, | ||
is DebugStepInst: | ||
break | ||
case let agi as AllocGlobalInst: | ||
if allocInst != nil { | ||
return nil | ||
} | ||
allocInst = agi | ||
case let ga as GlobalAddrInst: | ||
if globalAddr != nil { | ||
return nil | ||
} | ||
guard let agi = allocInst, agi.global == ga.global else { | ||
return nil | ||
} | ||
globalAddr = ga | ||
case let si as StoreInst: | ||
if store != nil { | ||
return nil | ||
} | ||
guard let ga = globalAddr else { | ||
return nil | ||
} | ||
if si.destination != ga { | ||
return nil | ||
} | ||
store = si | ||
default: | ||
if !inst.isValidInStaticInitializerOfGlobal { | ||
return nil | ||
} | ||
} | ||
} | ||
if let store = store { | ||
return (allocInst: allocInst!, storeToGlobal: store) | ||
} | ||
return nil | ||
} | ||
|
||
var singleBlock: BasicBlock? { | ||
let block = entryBlock | ||
if block.next != nil { | ||
return nil | ||
} | ||
return block | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyCondFail.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
//===--- SimplifyCondFail.swift -------------------------------------------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import SIL | ||
|
||
extension CondFailInst : OnoneSimplifyable { | ||
func simplify(_ context: SimplifyContext) { | ||
|
||
/// Eliminates | ||
/// ``` | ||
/// %0 = integer_literal 0 | ||
/// cond_fail %0, "message" | ||
/// ``` | ||
if let literal = condition as? IntegerLiteralInst, | ||
literal.value.isZero() { | ||
|
||
context.erase(instruction: self) | ||
} | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyDebugStep.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
//===--- SimplifyDebugStep.swift ------------------------------------------===// | ||
// | ||
// This source file is part of the Swift.org open source project | ||
// | ||
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors | ||
// Licensed under Apache License v2.0 with Runtime Library Exception | ||
// | ||
// See https://swift.org/LICENSE.txt for license information | ||
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import SIL | ||
|
||
extension DebugStepInst : Simplifyable { | ||
func simplify(_ context: SimplifyContext) { | ||
// When compiling with optimizations (note: it's not a OnoneSimplifyable transformation), | ||
// unconditionally remove debug_step instructions. | ||
context.erase(instruction: self) | ||
} | ||
} | ||
|
Oops, something went wrong.