Eti*_*e M 9 c++ assembly sse x86-64 floating-point-conversion
为什么AsDouble1比 更简单AsDouble0?
// AsDouble0(unsigned long): # @AsDouble0(unsigned long)
// movq xmm1, rdi
// punpckldq xmm1, xmmword ptr [rip + .LCPI0_0] # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
// subpd xmm1, xmmword ptr [rip + .LCPI0_1]
// movapd xmm0, xmm1
// unpckhpd xmm0, xmm1 # xmm0 = xmm0[1],xmm1[1]
// addsd xmm0, xmm1
// addsd xmm0, xmm0
// ret
double AsDouble0(uint64_t x) { return x * 2.0; }
// AsDouble1(unsigned long): # @AsDouble1(unsigned long)
// shr rdi
// cvtsi2sd xmm0, rdi
// addsd xmm0, xmm0
// ret
double AsDouble1(uint64_t x) { return (x >> 1) * 2.0; }
Run Code Online (Sandbox Code Playgroud)
代码位于: https: //godbolt.org/z/dKc6Pe6M1
x86 有一条在有符号整数和浮点数之间进行转换的指令。(我认为)AVX512 支持无符号整数转换,大多数编译器默认情况下并不支持这种转换。如果右移一次uint64_t,符号位就会消失,因此您可以将其解释为有符号整数并得到相同的结果。
该cvtsi2sd指令采用有符号整数(32 位或 64 位宽)作为其源操作数。但是,您的函数采用无符号参数。
因此,在第一种情况下,编译器无法直接使用该cvtsi2sd指令,因为给定参数中的值可能无法表示为相同大小的有符号整数 \xe2\x80\x93,因此它生成的代码将转换为double“很长一段路”(但安全)。
但是,在第二个函数中,初始右移一位可以保证符号位清晰;因此,无论将其解释为有符号还是无符号 \xe2\x80\xa6,结果值都将是相同的,因此编译器可以安全地使用该(修改后的)值作为操作的源cvtsi2sd。
| 归档时间: |
|
| 查看次数: |
288 次 |
| 最近记录: |