Skip to content

Commit 83b888c

Browse files
committed
InitializeStaticGlobals: support initializing globals with @_rawLayout types, like Atomic
Look through `@_rawLayout` projections, which "type casts" a raw-layout struct to it's content, which must match the like-type of the raw-layout, e.g. ``` @_rawLayout(like: T) struct S {} %2 = builtin "addressOfRawLayout"<S>(%1 : $*S) : $Builtin.RawPointer %3 = pointer_to_address %2 to $*T ```
1 parent 00afb7c commit 83b888c

File tree

2 files changed

+107
-12
lines changed

2 files changed

+107
-12
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/InitializeStaticGlobals.swift

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ private struct InitValueBuilder: AddressDefUseWalker {
358358
mutating func leafUse(address: Operand, path: UnusedWalkingPath) -> WalkResult {
359359
switch address.instruction {
360360
case let store as StoreInst:
361-
let accessPath = store.destination.constantAccessPath
361+
let accessPath = store.destination.lookThroughRawLayoutAddress.constantAccessPath
362362
switch accessPath.base {
363363
case .global, .stack:
364364
if !initValue.setElement(to: store.source, at: accessPath.projectionPath, type: originalAddress.type) {
@@ -385,8 +385,18 @@ private struct InitValueBuilder: AddressDefUseWalker {
385385
}
386386
case is LoadInst, is DeallocStackInst:
387387
return .continueWalk
388-
case let bi as BuiltinInst where bi.id == .PrepareInitialization:
389-
return .continueWalk
388+
case let bi as BuiltinInst:
389+
switch bi.id {
390+
case .PrepareInitialization:
391+
return .continueWalk
392+
case .AddressOfRawLayout:
393+
if let addr2Ptr = bi.uses.getSingleUser(ofType: PointerToAddressInst.self) {
394+
return walkDownUses(ofAddress: addr2Ptr, path: path)
395+
}
396+
return .abortWalk
397+
default:
398+
return .abortWalk
399+
}
390400
default:
391401
return .abortWalk
392402
}
@@ -466,14 +476,7 @@ private extension Function {
466476
case let alloc as AllocGlobalInst where alloc.global == global:
467477
return false
468478
case let store as StoreInst:
469-
switch store.destination.accessBase {
470-
case .global(let g) where g == global:
471-
return false
472-
case .stack:
473-
return false
474-
default:
475-
return true
476-
}
479+
return !store.destination.lookThroughRawLayoutAddress.isAddressOfStack(orGlobal: global)
477480
case let bi as BuiltinInst where bi.id == .PrepareInitialization:
478481
return false
479482
default:
@@ -496,3 +499,37 @@ private extension Function {
496499
context.removeTriviallyDeadInstructionsIgnoringDebugUses(in: self)
497500
}
498501
}
502+
503+
private extension Value {
504+
func isAddressOfStack(orGlobal global: GlobalVariable) -> Bool {
505+
switch accessBase {
506+
case .global(let g) where g == global:
507+
return true
508+
case .stack:
509+
return true
510+
default:
511+
return false
512+
}
513+
}
514+
515+
/// Looks through a `@_rawLayout` projection, which "type casts" a raw-layout struct to it's content, which
516+
/// must match the like-type of the raw-layout, e.g.
517+
/// ```
518+
/// @_rawLayout(like: T)
519+
/// struct S {}
520+
///
521+
/// %2 = builtin "addressOfRawLayout"<S>(%1 : $*S) : $Builtin.RawPointer
522+
/// %3 = pointer_to_address %2 to $*T
523+
/// ```
524+
var lookThroughRawLayoutAddress: Value {
525+
if let ptr2Addr = self as? PointerToAddressInst,
526+
let builtin = ptr2Addr.pointer as? BuiltinInst, builtin.id == .AddressOfRawLayout,
527+
let likeType = builtin.arguments[0].type.rawLayoutSubstitutedLikeType,
528+
builtin.arguments[0].type.rawLayoutSubstitutedCountType == nil,
529+
likeType.canonical == type.canonicalType
530+
{
531+
return builtin.arguments[0]
532+
}
533+
return self
534+
}
535+
}

test/SILOptimizer/init_static_globals.sil

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -initialize-static-globals | %FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -enable-experimental-feature RawLayout -initialize-static-globals | %FileCheck %s
22

33
// REQUIRES: swift_in_compiler
4+
// REQUIRES: swift_feature_RawLayout
45

56
sil_stage canonical
67

@@ -36,6 +37,12 @@ struct TwoFields {
3637
let b: Int32
3738
}
3839

40+
@_rawLayout(like: Int32)
41+
struct Raw: ~Copyable {}
42+
43+
@_rawLayout(likeArrayOf: Int32, count: 2)
44+
struct RawArray: ~Copyable {}
45+
3946
let nontrivialglobal: TClass
4047

4148
// CHECK-LABEL: sil_global hidden [let] @$trivialglobal : $TStruct = {
@@ -149,6 +156,18 @@ sil_global [let] @inline_array_empty_elements : $InlineArray<3, ()>
149156
// CHECK-NEXT: }
150157
sil_global [let] @gint : $Int32
151158

159+
// CHECK-LABEL: sil_global [let] @graw : $Raw = {
160+
// CHECK-NEXT: %0 = integer_literal $Builtin.Int32, 1
161+
// CHECK-NEXT: %initval = struct $Int32 (%0)
162+
// CHECK-NEXT: }
163+
sil_global [let] @graw: $Raw
164+
165+
// CHECK-LABEL: sil_global [let] @graw2 : $Raw{{$}}
166+
sil_global [let] @graw2: $Raw
167+
168+
// CHECK-LABEL: sil_global [let] @grawArray : $RawArray{{$}}
169+
sil_global [let] @grawArray: $RawArray
170+
152171
sil @unknownfunc : $@convention(thin) () -> ()
153172

154173
// CHECK-LABEL: sil [global_init_once_fn] [ossa] @globalinit_trivialglobal_func :
@@ -521,3 +540,42 @@ bb0(%0 : $Builtin.RawPointer):
521540
return %21
522541
}
523542

543+
sil [global_init_once_fn] [ossa] @globalinit_raw_layout: $@convention(c) (Builtin.RawPointer) -> () {
544+
bb0(%0 : $Builtin.RawPointer):
545+
alloc_global @graw
546+
%2 = global_addr @graw : $*Raw
547+
%3 = integer_literal $Builtin.Int32, 1
548+
%4 = struct $Int32 (%3)
549+
%5 = builtin "addressOfRawLayout"<Raw>(%2) : $Builtin.RawPointer
550+
%6 = pointer_to_address %5 to $*Int32
551+
store %4 to [trivial] %6
552+
%21 = tuple ()
553+
return %21
554+
}
555+
556+
sil [global_init_once_fn] [ossa] @no_globalinit_raw_layout_wrong_like_type: $@convention(c) (Builtin.RawPointer) -> () {
557+
bb0(%0 : $Builtin.RawPointer):
558+
alloc_global @graw
559+
%2 = global_addr @graw : $*Raw
560+
%3 = integer_literal $Builtin.Int16, 1
561+
%4 = struct $Int16 (%3)
562+
%5 = builtin "addressOfRawLayout"<Raw>(%2) : $Builtin.RawPointer
563+
%6 = pointer_to_address %5 to $*Int16
564+
store %4 to [trivial] %6
565+
%21 = tuple ()
566+
return %21
567+
}
568+
569+
sil [global_init_once_fn] [ossa] @no_globalinit_raw_layout_array: $@convention(c) (Builtin.RawPointer) -> () {
570+
bb0(%0 : $Builtin.RawPointer):
571+
alloc_global @grawArray
572+
%2 = global_addr @grawArray : $*RawArray
573+
%3 = integer_literal $Builtin.Int32, 1
574+
%4 = struct $Int32 (%3)
575+
%5 = builtin "addressOfRawLayout"<RawArray>(%2) : $Builtin.RawPointer
576+
%6 = pointer_to_address %5 to $*Int32
577+
store %4 to [trivial] %6
578+
%21 = tuple ()
579+
return %21
580+
}
581+

0 commit comments

Comments
 (0)