Skip to content

[SR-14101] Swift doesn't make global constants for constant arrays (should hoist array into global) #56487

@weissi

Description

@weissi
Previous ID SR-14101
Radar rdar://problem/73570149
Original Reporter @weissi
Type Bug
Status Resolved
Resolution Done
Environment
docker.io/swiftlang/swift:nightly-main-bionic
Swift version 5.4-dev (LLVM 7459512566cf7f4, Swift 8b5869ce6217b1f)
Target: x86_64-unknown-linux-gnu
Additional Detail from JIRA
Votes 0
Component/s
Labels Bug
Assignee None
Priority Medium

md5: 0f7004f7b8d04ae169dc87f69726168c

Issue Description:

consider this program

@inline(never)
func foo(_ x: String) throws -> Int {
    return #line + x.count
}

@inline(never)
func bar(_ x: String) throws -> Int {
    return #line + x.count
}

@inline(never)
func buz(_ x: String) throws -> Int {
    return #line + x.count
}

@inline(never)
func doIt() throws -> Int {
    var sum = 0
    for x in [foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              foo, bar, buz,
              ] {
        sum += try x("hello")
    }
    return sum
}

print(try! doIt())

The intermediate array is generated on each function invocation which generates a lot of code (and adds runtime overhead). I would've hoped that Swift realises that the array is in fact constant, then it could've put that in a global and initialised it just once.

The code looks like (with both -O and -Osize)

swiftc -emit-assembly -O test.swift  | swift demangle | grep -A100 ^test.doIt
test.doIt() throws -> Swift.Int:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    pushq   %r15
    .cfi_def_cfa_offset 24
    pushq   %r14
    .cfi_def_cfa_offset 32
    pushq   %r13
    .cfi_def_cfa_offset 40
    pushq   %rbx
    .cfi_def_cfa_offset 48
    subq    $48, %rsp
    .cfi_def_cfa_offset 96
    .cfi_offset %rbx, -48
    .cfi_offset %r13, -40
    .cfi_offset %r14, -32
    .cfi_offset %r15, -24
    .cfi_offset %rbp, -16
    movq    %r12, 16(%rsp)
    leaq    (demangling cache variable for type metadata for Swift._ContiguousArrayStorage<(Swift.String) throws -> Swift.Int>)(%rip), %rdi
    callq   __swift_instantiateConcreteTypeFromMangledName
    movl    $1040, %esi
    movl    $7, %edx
    movq    %rax, %rdi
    callq   swift_allocObject@PLT
    movaps  .LCPI5_0(%rip), %xmm0
    movups  %xmm0, 16(%rax)
    leaq    (function signature specialization <Arg[2] = [Constant Propagated Function : test.foo(Swift.String) throws -> Swift.Int]> of reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed Swift.String) -> (@unowned Swift.Int, @error @owned Swift.Error) to @escaping @callee_guaranteed (@in_guaranteed Swift.String) -> (@out Swift.Int, @error @owned Swift.Error))(%rip), %rsi
    movq    %rsi, 32(%rax)
    movq    $0, 40(%rax)
    leaq    (function signature specialization <Arg[2] = [Constant Propagated Function : test.bar(Swift.String) throws -> Swift.Int]> of reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed Swift.String) -> (@unowned Swift.Int, @error @owned Swift.Error) to @escaping @callee_guaranteed (@in_guaranteed Swift.String) -> (@out Swift.Int, @error @owned Swift.Error))(%rip), %rcx
    movq    %rcx, 48(%rax)
    movq    $0, 56(%rax)
    leaq    (function signature specialization <Arg[2] = [Constant Propagated Function : test.buz(Swift.String) throws -> Swift.Int]> of reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed Swift.String) -> (@unowned Swift.Int, @error @owned Swift.Error) to @escaping @callee_guaranteed (@in_guaranteed Swift.String) -> (@out Swift.Int, @error @owned Swift.Error))(%rip), %rdx
    movq    %rdx, 64(%rax)
    movq    $0, 72(%rax)
    movq    %rsi, 80(%rax)
    movq    $0, 88(%rax)
    movq    %rcx, 96(%rax)
    movq    $0, 104(%rax)
    movq    %rdx, 112(%rax)
    movq    $0, 120(%rax)
    movq    %rsi, 128(%rax)
    movq    $0, 136(%rax)
    movq    %rcx, 144(%rax)
    movq    $0, 152(%rax)
    movq    %rdx, 160(%rax)
    movq    $0, 168(%rax)
    movq    %rsi, 176(%rax)
    movq    $0, 184(%rax)
    movq    %rcx, 192(%rax)
    movq    $0, 200(%rax)
    movq    %rdx, 208(%rax)
    movq    $0, 216(%rax)
    movq    %rsi, 224(%rax)
    movq    $0, 232(%rax)
    movq    %rcx, 240(%rax)
    movq    $0, 248(%rax)
    movq    %rdx, 256(%rax)
    movq    $0, 264(%rax)
    movq    %rsi, 272(%rax)
    movq    $0, 280(%rax)
    movq    %rcx, 288(%rax)
    movq    $0, 296(%rax)
    movq    %rdx, 304(%rax)
    movq    $0, 312(%rax)
    movq    %rsi, 320(%rax)
    movq    $0, 328(%rax)
    movq    %rcx, 336(%rax)
    movq    $0, 344(%rax)
    movq    %rdx, 352(%rax)
    movq    $0, 360(%rax)
    movq    %rsi, 368(%rax)
    movq    $0, 376(%rax)
    movq    %rcx, 384(%rax)
    movq    $0, 392(%rax)
    movq    %rdx, 400(%rax)
    movq    $0, 408(%rax)
    movq    %rsi, 416(%rax)
    movq    $0, 424(%rax)
    movq    %rcx, 432(%rax)
    movq    $0, 440(%rax)
    movq    %rdx, 448(%rax)
    movq    $0, 456(%rax)
    movq    %rsi, 464(%rax)
    movq    $0, 472(%rax)
    movq    %rcx, 480(%rax)
    movq    $0, 488(%rax)
    movq    %rdx, 496(%rax)
    movq    $0, 504(%rax)
    movq    %rsi, 512(%rax)
    movq    $0, 520(%rax)
    movq    %rcx, 528(%rax)
    movq    $0, 536(%rax)
    movq    %rdx, 544(%rax)
    movq    $0, 552(%rax)
    movq    %rsi, 560(%rax)
    movq    $0, 568(%rax)
    movq    %rcx, 576(%rax)
    movq    $0, 584(%rax)
        [...]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugA deviation from expected or documented behavior. Also: expected but undesirable behavior.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions