Skip to content

Commit 0ceb517

Browse files
authored
Merge pull request swiftlang#81649 from eeckstein/global-inlinearray-initialization
Allow more complex InlineArray initializations to end up in a statically initialized global
2 parents 490edfa + 47db3fc commit 0ceb517

25 files changed

+653
-392
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift

Lines changed: 389 additions & 259 deletions
Large diffs are not rendered by default.

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,75 @@ private extension Instruction {
376376
return shiftValue > 0
377377
}
378378
}
379+
380+
/// Analyses the global initializer function and returns the `alloc_global` and `store`
381+
/// instructions which initialize the global.
382+
/// Returns nil if `function` has any side-effects beside initializing the global.
383+
///
384+
/// The function's single basic block must contain following code pattern:
385+
/// ```
386+
/// alloc_global @the_global
387+
/// %a = global_addr @the_global
388+
/// %i = some_const_initializer_insts
389+
/// store %i to %a
390+
/// ```
391+
///
392+
/// For all other instructions `handleUnknownInstruction` is called and such an instruction
393+
/// is accepted if `handleUnknownInstruction` returns true.
394+
private func getGlobalInitialization(
395+
of function: Function,
396+
_ context: some Context,
397+
handleUnknownInstruction: (Instruction) -> Bool
398+
) -> (allocInst: AllocGlobalInst, storeToGlobal: StoreInst)? {
399+
guard let block = function.blocks.singleElement else {
400+
return nil
401+
}
402+
403+
var allocInst: AllocGlobalInst? = nil
404+
var globalAddr: GlobalAddrInst? = nil
405+
var store: StoreInst? = nil
406+
407+
for inst in block.instructions {
408+
switch inst {
409+
case is ReturnInst,
410+
is DebugValueInst,
411+
is DebugStepInst,
412+
is BeginAccessInst,
413+
is EndAccessInst:
414+
continue
415+
case let agi as AllocGlobalInst:
416+
if allocInst == nil {
417+
allocInst = agi
418+
continue
419+
}
420+
case let ga as GlobalAddrInst:
421+
if let agi = allocInst, agi.global == ga.global {
422+
globalAddr = ga
423+
}
424+
continue
425+
case let si as StoreInst:
426+
if store == nil,
427+
let ga = globalAddr,
428+
si.destination == ga
429+
{
430+
store = si
431+
continue
432+
}
433+
// Note that the initializer must not contain a `global_value` because `global_value` needs to
434+
// initialize the class metadata at runtime.
435+
default:
436+
if inst.isValidInStaticInitializerOfGlobal(context) {
437+
continue
438+
}
439+
}
440+
if handleUnknownInstruction(inst) {
441+
continue
442+
}
443+
return nil
444+
}
445+
if let store = store {
446+
return (allocInst: allocInst!, storeToGlobal: store)
447+
}
448+
return nil
449+
}
450+

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyPointerToAddress.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -293,13 +293,6 @@ private extension Value {
293293
return self
294294
}
295295
}
296-
297-
var lookThroughTruncOrBitCast: Value {
298-
if let truncOrBitCast = self as? BuiltinInst, truncOrBitCast.id == .TruncOrBitCast {
299-
return truncOrBitCast.arguments[0]
300-
}
301-
return self
302-
}
303296
}
304297

305298
private extension BuiltinInst {

SwiftCompilerSources/Sources/Optimizer/Utilities/AddressUtils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ extension AddressUseVisitor {
159159
.GenericFDiv, .GenericMul, .GenericFMul, .GenericSDiv,
160160
.GenericExactSDiv, .GenericShl, .GenericSRem, .GenericSub,
161161
.GenericFSub, .GenericUDiv, .GenericExactUDiv, .GenericURem,
162-
.GenericFRem, .GenericXor, .TaskRunInline, .ZeroInitializer,
162+
.GenericFRem, .GenericXor, .TaskRunInline, .ZeroInitializer, .PrepareInitialization,
163163
.GetEnumTag, .InjectEnumTag:
164164
return leafAddressUse(of: operand)
165165
default:

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 7 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@ extension Value {
4545
}
4646
}
4747

48+
var lookThroughTruncOrBitCast: Value {
49+
if let truncOrBitCast = self as? BuiltinInst, truncOrBitCast.id == .TruncOrBitCast {
50+
return truncOrBitCast.arguments[0]
51+
}
52+
return self
53+
}
54+
4855
func isInLexicalLiverange(_ context: some Context) -> Bool {
4956
var worklist = ValueWorklist(context)
5057
defer { worklist.deinitialize() }
@@ -846,77 +853,6 @@ extension InstructionRange {
846853
}
847854
}
848855

849-
/// Analyses the global initializer function and returns the `alloc_global` and `store`
850-
/// instructions which initialize the global.
851-
/// Returns nil if `function` has any side-effects beside initializing the global.
852-
///
853-
/// The function's single basic block must contain following code pattern:
854-
/// ```
855-
/// alloc_global @the_global
856-
/// %a = global_addr @the_global
857-
/// %i = some_const_initializer_insts
858-
/// store %i to %a
859-
/// ```
860-
///
861-
/// For all other instructions `handleUnknownInstruction` is called and such an instruction
862-
/// is accepted if `handleUnknownInstruction` returns true.
863-
func getGlobalInitialization(
864-
of function: Function,
865-
_ context: some Context,
866-
handleUnknownInstruction: (Instruction) -> Bool
867-
) -> (allocInst: AllocGlobalInst, storeToGlobal: StoreInst)? {
868-
guard let block = function.blocks.singleElement else {
869-
return nil
870-
}
871-
872-
var allocInst: AllocGlobalInst? = nil
873-
var globalAddr: GlobalAddrInst? = nil
874-
var store: StoreInst? = nil
875-
876-
for inst in block.instructions {
877-
switch inst {
878-
case is ReturnInst,
879-
is DebugValueInst,
880-
is DebugStepInst,
881-
is BeginAccessInst,
882-
is EndAccessInst:
883-
continue
884-
case let agi as AllocGlobalInst:
885-
if allocInst == nil {
886-
allocInst = agi
887-
continue
888-
}
889-
case let ga as GlobalAddrInst:
890-
if let agi = allocInst, agi.global == ga.global {
891-
globalAddr = ga
892-
}
893-
continue
894-
case let si as StoreInst:
895-
if store == nil,
896-
let ga = globalAddr,
897-
si.destination == ga
898-
{
899-
store = si
900-
continue
901-
}
902-
// Note that the initializer must not contain a `global_value` because `global_value` needs to
903-
// initialize the class metadata at runtime.
904-
default:
905-
if inst.isValidInStaticInitializerOfGlobal(context) {
906-
continue
907-
}
908-
}
909-
if handleUnknownInstruction(inst) {
910-
continue
911-
}
912-
return nil
913-
}
914-
if let store = store {
915-
return (allocInst: allocInst!, storeToGlobal: store)
916-
}
917-
return nil
918-
}
919-
920856
func canDynamicallyCast(from sourceType: CanonicalType, to destType: CanonicalType,
921857
in function: Function, sourceTypeIsExact: Bool
922858
) -> Bool? {

SwiftCompilerSources/Sources/SIL/GlobalVariable.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ final public class GlobalVariable : CustomStringConvertible, HasShortDescription
2929

3030
public var shortDescription: String { name.string }
3131

32+
public var type: Type { Type(bridged: bridged.getType()) }
33+
3234
public var isLet: Bool { bridged.isLet() }
3335

3436
public var linkage: Linkage { bridged.getLinkage().linkage }

include/swift/AST/Builtins.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,10 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(Alignof, "alignof", "n", Special)
851851
/// own rules.
852852
BUILTIN_MISC_OPERATION_WITH_SILGEN(ZeroInitializer, "zeroInitializer", "n", Special)
853853

854+
/// Like `zeroInitializer`, but does not actually initialize the memory.
855+
/// It only indicates to mandatory passes that the memory is going to be initialized.
856+
BUILTIN_MISC_OPERATION(PrepareInitialization, "prepareInitialization", "n", Special)
857+
854858
// getCurrentExecutor: () async -> Builtin.Executor?
855859
//
856860
// Retrieve the SerialExecutorRef on which the current asynchronous

include/swift/SIL/AddressWalker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ TransitiveAddressWalker<Impl>::walk(SILValue projectedAddress) {
288288
case BuiltinValueKind::GenericXor:
289289
case BuiltinValueKind::TaskRunInline:
290290
case BuiltinValueKind::ZeroInitializer:
291+
case BuiltinValueKind::PrepareInitialization:
291292
case BuiltinValueKind::GetEnumTag:
292293
case BuiltinValueKind::InjectEnumTag:
293294
case BuiltinValueKind::AddressOfRawLayout:

include/swift/SIL/SILBridging.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ struct BridgedGlobalVar {
587587
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedStringRef getName() const;
588588
BRIDGED_INLINE bool isLet() const;
589589
BRIDGED_INLINE void setLet(bool value) const;
590+
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getType() const;
590591
BRIDGED_INLINE BridgedLinkage getLinkage() const;
591592
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSourceLoc getSourceLocation() const;
592593
BRIDGED_INLINE bool isPossiblyUsedExternally() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,10 @@ bool BridgedGlobalVar::isLet() const { return getGlobal()->isLet(); }
918918

919919
void BridgedGlobalVar::setLet(bool value) const { getGlobal()->setLet(value); }
920920

921+
BridgedType BridgedGlobalVar::getType() const {
922+
return getGlobal()->getLoweredType();
923+
}
924+
921925
BridgedLinkage BridgedGlobalVar::getLinkage() const {
922926
return (BridgedLinkage)getGlobal()->getLinkage();
923927
}

0 commit comments

Comments
 (0)