Open
Description
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).