Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-15215] Excessive outlined init with takes when using optionals #57537

Open
karwa opened this issue Sep 19, 2021 · 2 comments
Open

[SR-15215] Excessive outlined init with takes when using optionals #57537

karwa opened this issue Sep 19, 2021 · 2 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@karwa
Copy link
Contributor

karwa commented Sep 19, 2021

Previous ID SR-15215
Radar rdar://problem/83297558
Original Reporter @karwa
Type Bug
Environment

Swift version 5.6-dev (LLVM 70b82c8b83f6294, Swift a66435c)
Target: x86_64-unknown-linux-gnu

Additional Detail from JIRA
Votes 1
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: 8c58205ab47b0a9798dd31351dc797cd

Issue Description:

Consider the following code:

func test(_ input: HasAnEnum) -> Int {
    input.readValue()
}

enum MyEnum {
    case one
    case four
}

struct HasAnEnum {
    var s1: String
    var s2: String
    var s3: String
    var s4: String
    var s5: String
    var s6: String
    var s7: String
    var s8: String
    var s9: String
    var s10: String
    var value: MyEnum    

    func readValue() -> Int {
        let x = value
        if case .four = x { return 4 }
        return -1
    }
}

In an optimised build, this generates the following assembly (Godbolt):

output.test(output.HasAnEnum) -> Swift.Int:
        movzx   eax, byte ptr [rdi + 160]
        lea     rax, [rax + 4*rax]
        add     rax, -1
        ret

Short, sweet. Just what you'd expect, right?

Now, let's add one character and watch the world go up in flames:

struct HasAnEnum {
    // ...
    var value: MyEnum? // <- Make this an optional
}
output.test(output.HasAnEnum) -> Swift.Int:
        push    rbx
        sub     rsp, 16
        add     rdi, 160
        lea     rbx, [rsp + 8]
        mov     rsi, rbx
        call    (outlined init with take of output.MyEnum?)
        mov     rsi, rsp
        mov     rdi, rbx
        call    (outlined init with take of output.MyEnum?)
        movzx   eax, byte ptr [rsp]
        mov     ecx, eax
        and     ecx, 1
        cmp     rax, 2
        lea     rcx, [rcx + 4*rcx - 1]
        mov     rax, -1
        cmovne  rax, rcx
        add     rsp, 16
        pop     rbx
        ret

Boom. Now we're calling a bunch of runtime functions, and this code suddenly performs much worse while also being much larger.

In my code, this is a major performance issue. It dominates almost everything else we do... just to load a stored optional enum.

(This trace is from a function which writes a normalized URL string using scanned ranges from an input string. As you can see, the only thing more expensive than this is parsing/writing the path string, which has to simplify arbitrarily long and complex paths and percent-encode them. That's how expensive it is).

In fact, >8% of the time spent writing the URL string is the load of this one optional. Wild.

@karwa
Copy link
Contributor Author

karwa commented Sep 19, 2021

@Lukasa
Copy link
Contributor

Lukasa commented Sep 20, 2021

@swift-ci create

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

2 participants