Passing [Mutable][Raw]Span as inout optimization

I found that passing [Mutable][Raw]Span as inout produces more instructions in caller function (initialization of span) and additional instruction in callee side for getting pointer ( If I understand it correctly). Is this a missed optimization?

Example with MutableSpan


@inline(never)
func borrowingCaller() -> Int {
    var arr: [3 of Int] = [1,2,3]
    var span = arr.mutableSpan
    return borrowingCallee(span)
}

@inline(never)
func borrowingCallee(_ span: borrowing MutableSpan<Int>) -> Int {
    return span[1]
}

@inline(never)
func inoutCaller() -> Int {
    var arr: [3 of Int] = [1,2,3]
    var span = arr.mutableSpan
    return inoutCallee(&span)
}

@inline(never)
func inoutCallee(_ span: inout MutableSpan<Int>) -> Int {
    return span[1]
}

Swift 6.2 -Ounchecked -disable-stack-protector

output.borrowingCaller() -> Swift.Int:
        sub     rsp, 24
        mov     qword ptr [rsp], 1
        mov     qword ptr [rsp + 8], 2
        mov     qword ptr [rsp + 16], 3
        mov     rdi, rsp
        call    (output.borrowingCallee(Swift.MutableSpan<Swift.Int>) -> Swift.Int)
        add     rsp, 24
        ret

output.borrowingCallee(Swift.MutableSpan<Swift.Int>) -> Swift.Int:
        mov     rax, qword ptr [rdi + 8]
        ret

output.inoutCaller() -> Swift.Int:
        sub     rsp, 40
        mov     qword ptr [rsp + 16], 1
        mov     qword ptr [rsp + 24], 2
        mov     qword ptr [rsp + 32], 3
        lea     rax, [rsp + 16]
        mov     qword ptr [rsp], rax
        mov     qword ptr [rsp + 8], 3
        mov     rdi, rsp
        call    (output.inoutCallee(inout Swift.MutableSpan<Swift.Int>) -> Swift.Int)
        add     rsp, 40
        ret

output.inoutCallee(inout Swift.MutableSpan<Swift.Int>) -> Swift.Int:
        mov     rax, qword ptr [rdi]
        mov     rax, qword ptr [rax + 8]
        ret

Ah, I see what's happening here.

A span is a pointer. When you pass something inout, you pass a pointer to it. So the reason there's two mov instructions here (as opposed to one in the borrowing version) is that it has to dereference the pointer it's been passed before indexing the span.

I don't fully understand the difference in the caller, but I would assume it's something similar.