Skip to content

Libcalls for Windows without SSE should return i128 on the stack #127723

Open
@tgross35

Description

@tgross35

The following:

attributes #0 = { "target-features"="-mmx,-sse,+soft-float" }

define void @do_div(ptr %xptr, ptr %yptr, ptr %rptr) #0 {
  %x = load i128, ptr %xptr
  %y = load i128, ptr %yptr
  %res = udiv i128 %x, %y
  store i128 %res, ptr %rptr
  ret void
}

On x86_64-pc-windows-msvc generates:

do_div:                                 # @do_div
        push    rsi
        sub     rsp, 64
        mov     rsi, r8
        mov     rax, qword ptr [rcx]
        mov     rcx, qword ptr [rcx + 8]
        mov     r8, qword ptr [rdx]
        mov     rdx, qword ptr [rdx + 8]
        mov     qword ptr [rsp + 56], rcx
        mov     qword ptr [rsp + 48], rax
        mov     qword ptr [rsp + 32], r8
        mov     qword ptr [rsp + 40], rdx
        lea     rcx, [rsp + 48]
        lea     rdx, [rsp + 32]
        call    __udivti3
        mov     qword ptr [rsi], rax
        mov     qword ptr [rsi + 8], rdx
        add     rsp, 64
        pop     rsi
        ret

Link: https://llvm.godbolt.org/z/bcao4bdj1

In do_div, LLVM seems to expect __udivti3 to takes its arguments indirectly but return in a register pair (rax, rdx). This doesn't seem correct; nothing in the Windows calling convention suggests that values larger than 64 bits are ever returned in registers. Instead, i128 should be returned in a stack slot if sse is not available.

i128 is usually returned in xmm0, and the default is to both pass and return i128 in registers, so this seems like it may just be fallback behavior.

There is more at rust-lang/compiler-builtins#758, specifically this comment rust-lang/compiler-builtins#758 (comment).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions