Skip to content

Commit ec6f725

Browse files
committed
SwiftCompilerSources: move some private utilities of passes into OptUtils
* `var Function.initializedGlobal` * `func getGlobalInitialization` and add `var CollectionLikeSequence.singleElement`
1 parent 9a34039 commit ec6f725

File tree

4 files changed

+91
-85
lines changed

4 files changed

+91
-85
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/AllocVectorLowering.swift

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -441,17 +441,3 @@ private extension StoreInst {
441441
return false
442442
}
443443
}
444-
445-
private extension Function {
446-
var initializedGlobal: GlobalVariable? {
447-
if !isGlobalInitOnceFunction {
448-
return nil
449-
}
450-
for inst in entryBlock.instructions {
451-
if let allocGlobal = inst as? AllocGlobalInst {
452-
return allocGlobal.global
453-
}
454-
}
455-
return nil
456-
}
457-
}

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift

Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ let initializeStaticGlobalsPass = FunctionPass(name: "initialize-static-globals"
5757
// Merge such individual stores to a single store of the whole struct.
5858
mergeStores(in: function, context)
5959

60-
guard let (allocInst, storeToGlobal) = getGlobalInitialization(of: function) else {
60+
// The initializer must not contain a `global_value` because `global_value` needs to
61+
// initialize the class metadata at runtime.
62+
guard let (allocInst, storeToGlobal) = getGlobalInitialization(of: function, allowGlobalValue: false) else {
6163
return
6264
}
6365

@@ -81,76 +83,6 @@ let initializeStaticGlobalsPass = FunctionPass(name: "initialize-static-globals"
8183
context.removeTriviallyDeadInstructionsIgnoringDebugUses(in: function)
8284
}
8385

84-
/// Analyses the global initializer function and returns the `alloc_global` and `store`
85-
/// instructions which initialize the global.
86-
///
87-
/// The function's single basic block must contain following code pattern:
88-
/// ```
89-
/// alloc_global @the_global
90-
/// %a = global_addr @the_global
91-
/// %i = some_const_initializer_insts
92-
/// store %i to %a
93-
/// ```
94-
private func getGlobalInitialization(of function: Function) -> (allocInst: AllocGlobalInst, storeToGlobal: StoreInst)? {
95-
96-
guard let block = function.singleBlock else {
97-
return nil
98-
}
99-
100-
var allocInst: AllocGlobalInst? = nil
101-
var globalAddr: GlobalAddrInst? = nil
102-
var store: StoreInst? = nil
103-
104-
for inst in block.instructions {
105-
switch inst {
106-
case is ReturnInst,
107-
is DebugValueInst,
108-
is DebugStepInst,
109-
is BeginAccessInst,
110-
is EndAccessInst:
111-
break
112-
case let agi as AllocGlobalInst:
113-
if allocInst != nil {
114-
return nil
115-
}
116-
allocInst = agi
117-
case let ga as GlobalAddrInst:
118-
if let agi = allocInst, agi.global == ga.global {
119-
globalAddr = ga
120-
}
121-
case let si as StoreInst:
122-
if store != nil {
123-
return nil
124-
}
125-
guard let ga = globalAddr else {
126-
return nil
127-
}
128-
if si.destination != ga {
129-
return nil
130-
}
131-
store = si
132-
default:
133-
if !inst.isValidInStaticInitializerOfGlobal {
134-
return nil
135-
}
136-
}
137-
}
138-
if let store = store {
139-
return (allocInst: allocInst!, storeToGlobal: store)
140-
}
141-
return nil
142-
}
143-
144-
private extension Function {
145-
var singleBlock: BasicBlock? {
146-
let block = entryBlock
147-
if block.next != nil {
148-
return nil
149-
}
150-
return block
151-
}
152-
}
153-
15486
/// Merges stores to individual struct fields to a single store of the whole struct.
15587
///
15688
/// store %element1 to %element1Addr

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,18 @@ extension Function {
484484
}
485485
return nil
486486
}
487+
488+
var initializedGlobal: GlobalVariable? {
489+
if !isGlobalInitOnceFunction {
490+
return nil
491+
}
492+
for inst in entryBlock.instructions {
493+
if let allocGlobal = inst as? AllocGlobalInst {
494+
return allocGlobal.global
495+
}
496+
}
497+
return nil
498+
}
487499
}
488500

489501
extension FullApplySite {
@@ -570,3 +582,68 @@ extension InstructionRange {
570582
}
571583
}
572584
}
585+
586+
/// Analyses the global initializer function and returns the `alloc_global` and `store`
587+
/// instructions which initialize the global.
588+
/// Returns nil if `function` has any side-effects beside initializing the global.
589+
///
590+
/// The function's single basic block must contain following code pattern:
591+
/// ```
592+
/// alloc_global @the_global
593+
/// %a = global_addr @the_global
594+
/// %i = some_const_initializer_insts
595+
/// store %i to %a
596+
/// ```
597+
func getGlobalInitialization(
598+
of function: Function,
599+
allowGlobalValue: Bool
600+
) -> (allocInst: AllocGlobalInst, storeToGlobal: StoreInst)? {
601+
guard let block = function.blocks.singleElement else {
602+
return nil
603+
}
604+
605+
var allocInst: AllocGlobalInst? = nil
606+
var globalAddr: GlobalAddrInst? = nil
607+
var store: StoreInst? = nil
608+
609+
for inst in block.instructions {
610+
switch inst {
611+
case is ReturnInst,
612+
is DebugValueInst,
613+
is DebugStepInst,
614+
is BeginAccessInst,
615+
is EndAccessInst:
616+
break
617+
case let agi as AllocGlobalInst:
618+
if allocInst != nil {
619+
return nil
620+
}
621+
allocInst = agi
622+
case let ga as GlobalAddrInst:
623+
if let agi = allocInst, agi.global == ga.global {
624+
globalAddr = ga
625+
}
626+
case let si as StoreInst:
627+
if store != nil {
628+
return nil
629+
}
630+
guard let ga = globalAddr else {
631+
return nil
632+
}
633+
if si.destination != ga {
634+
return nil
635+
}
636+
store = si
637+
case is GlobalValueInst where allowGlobalValue:
638+
break
639+
default:
640+
if !inst.isValidInStaticInitializerOfGlobal {
641+
return nil
642+
}
643+
}
644+
}
645+
if let store = store {
646+
return (allocInst: allocInst!, storeToGlobal: store)
647+
}
648+
return nil
649+
}

SwiftCompilerSources/Sources/SIL/Utilities/SequenceUtilities.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ public protocol CollectionLikeSequence : FormattedLikeArray {
8787

8888
public extension CollectionLikeSequence {
8989
var isEmpty: Bool { !contains(where: { _ in true }) }
90+
91+
var singleElement: Element? {
92+
var singleElement: Element? = nil
93+
for e in self {
94+
if singleElement != nil {
95+
return nil
96+
}
97+
singleElement = e
98+
}
99+
return singleElement
100+
}
90101
}
91102

92103
// Also make the lazy sequences a CollectionLikeSequence if the underlying sequence is one.

0 commit comments

Comments
 (0)