Issue 127723
Summary Libcalls for Windows without SSE should return `i128` on the stack
Labels new issue
Assignees
Reporter tgross35
    The following:

```llvm
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
}
```

Generates:

```asm
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 https://github.com/rust-lang/compiler-builtins/issues/758, specifically this comment https://github.com/rust-lang/compiler-builtins/issues/758#issuecomment-2667130322.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to