sqint of uint64_t vs. int64_t

Hin*_*rik 8 x86 assembly sse compilation square-root

我注意到计算平方根的整数部分uint64_t要复杂得多int64_t.请问有人对此有解释吗?为什么处理一个额外的位似乎要困难得多?

下列:

int64_t sqrt_int(int64_t a) {
    return sqrt(a);
}
Run Code Online (Sandbox Code Playgroud)

与铛5.0和编译-mfpmath=sse -msse3 -Wall -O3

sqrt_int(long):                           # @sqrt_int(long)
        cvtsi2sd        xmm0, rdi
        sqrtsd  xmm0, xmm0
        cvttsd2si       rax, xmm0
        ret
Run Code Online (Sandbox Code Playgroud)

但是以下内容:

uint64_t sqrt_int(uint64_t a) {
    return sqrt(a);
}
Run Code Online (Sandbox Code Playgroud)

编译为:

.LCPI0_0:
        .long   1127219200              # 0x43300000
        .long   1160773632              # 0x45300000
        .long   0                       # 0x0
        .long   0                       # 0x0
.LCPI0_1:
        .quad   4841369599423283200     # double 4503599627370496
        .quad   4985484787499139072     # double 1.9342813113834067E+25
.LCPI0_2:
        .quad   4890909195324358656     # double 9.2233720368547758E+18
sqrt_int(unsigned long):                           # @sqrt_int(unsigned long)
        movq    xmm0, rdi
        punpckldq       xmm0, xmmword ptr [rip + .LCPI0_0] # xmm0 = xmm0[0],mem[0],xmm0[1],mem[1]
        subpd   xmm0, xmmword ptr [rip + .LCPI0_1]
        haddpd  xmm0, xmm0
        sqrtsd  xmm0, xmm0
        movsd   xmm1, qword ptr [rip + .LCPI0_2] # xmm1 = mem[0],zero
        movapd  xmm2, xmm0
        subsd   xmm2, xmm1
        cvttsd2si       rax, xmm2
        movabs  rcx, -9223372036854775808
        xor     rcx, rax
        cvttsd2si       rax, xmm0
        ucomisd xmm0, xmm1
        cmovae  rax, rcx
        ret
Run Code Online (Sandbox Code Playgroud)

Zal*_*ern 11

首先,您需要清楚此代码将64位整数(有符号或无符号)转换为双精度浮点,取平方根,然后将结果转换回有符号或无符号整数.

您的问题的答案是因为英特尔在您编译的指令集中提供了64位有符号整数到双精度浮点转换(相反),但对于无符号情况则没有这样做.他们在AVX-512中添加了无符号转换指令,但在此之前不存在.因此,对于已签名的情况,转换为双精度和转换返回是每个指令.对于无符号的情况,编译器必须从可用指令合成转换操作.

您可以在此处获取有关哪些版本的SSE2/AVX/AVX-512等可用指令的信息:https: //software.intel.com/sites/landingpage/IntrinsicsGuide/

您可以在此处看到用于合成转换的方法的讨论: 是否有x87 FILD和SSE CVTSI2SD指令的无符号等效项?