gpt4 book ai didi

c - 浮点到双转换 : why so many instructions?

转载 作者:太空狗 更新时间:2023-10-29 16:28:51 25 4
gpt4 key购买 nike

我很好奇是否有人可以为我阐明这一点。我正在研究一些数字数据转换的东西,我有几个进行数据转换的函数,我使用两个宏定义它们:

#define CONV_VIA_CAST(name, dtype, vtype)                               \
static inline void name(void *data, void *view, size_t len) { \
vtype *vptr = (vtype*)view; \
dtype *dptr = (dtype*)data; \
for (size_t ii=0; ii < len/sizeof(vtype); ii++) { \
*vptr++ = (vtype)*dptr++; \
} \
}


#define CONV_VIA_FUNC(name, dtype, vtype, via) \
static inline void name(void *data, void *view, size_t len) { \
vtype *vptr = (vtype*)view; \
dtype *dptr = (dtype*)data; \
for (size_t ii=0; ii < len/sizeof(vtype); ii++) { \
*vptr++ = (vtype)via(*dptr++); \
} \
}

当我定义一个 float 到 int 的转换时:

 CONV_VIA_FUNC(f_to_i, float, int16_t, lrintf); 

我用 -O3 得到了一个漂亮简洁的小片段:

   0x0000000000401fb0 <+0>:     shr    %rdx
0x0000000000401fb3 <+3>: je 0x401fd3 <f_to_i+35>
0x0000000000401fb5 <+5>: xor %eax,%eax
0x0000000000401fb7 <+7>: nopw 0x0(%rax,%rax,1)
0x0000000000401fc0 <+16>: cvtss2si (%rdi,%rax,4),%rcx
0x0000000000401fc6 <+22>: mov %cx,(%rsi,%rax,2)
0x0000000000401fca <+26>: add $0x1,%rax
0x0000000000401fce <+30>: cmp %rdx,%rax
0x0000000000401fd1 <+33>: jne 0x401fc0 <f_to_i+16>
0x0000000000401fd3 <+35>: repz retq

但是,当我定义一个 float->double(或 double->float)函数时:

CONV_VIA_CAST(f_to_d, float,   double); 

我得到了这个怪物:

   0x0000000000402040 <+0>:     mov    %rdx,%r8
0x0000000000402043 <+3>: shr $0x3,%r8
0x0000000000402047 <+7>: test %r8,%r8
0x000000000040204a <+10>: je 0x402106 <f_to_d+198>
0x0000000000402050 <+16>: shr $0x5,%rdx
0x0000000000402054 <+20>: lea 0x0(,%rdx,4),%r9
0x000000000040205c <+28>: test %r9,%r9
0x000000000040205f <+31>: je 0x402108 <f_to_d+200>
0x0000000000402065 <+37>: lea (%rdi,%r8,4),%rax
0x0000000000402069 <+41>: cmp $0xb,%r8
0x000000000040206d <+45>: lea (%rsi,%r8,8),%r10
0x0000000000402071 <+49>: seta %cl
0x0000000000402074 <+52>: cmp %rax,%rsi
0x0000000000402077 <+55>: seta %al
0x000000000040207a <+58>: cmp %r10,%rdi
0x000000000040207d <+61>: seta %r10b
0x0000000000402081 <+65>: or %r10d,%eax
0x0000000000402084 <+68>: test %al,%cl
0x0000000000402086 <+70>: je 0x402108 <f_to_d+200>
0x000000000040208c <+76>: xorps %xmm3,%xmm3
0x000000000040208f <+79>: xor %eax,%eax
0x0000000000402091 <+81>: xor %ecx,%ecx
0x0000000000402093 <+83>: nopl 0x0(%rax,%rax,1)
0x0000000000402098 <+88>: movaps %xmm3,%xmm0
0x000000000040209b <+91>: add $0x1,%rcx
0x000000000040209f <+95>: movlps (%rdi,%rax,1),%xmm0
0x00000000004020a3 <+99>: movhps 0x8(%rdi,%rax,1),%xmm0
0x00000000004020a8 <+104>: movhlps %xmm0,%xmm1
0x00000000004020ab <+107>: cvtps2pd %xmm0,%xmm2
0x00000000004020ae <+110>: cvtps2pd %xmm1,%xmm0
0x00000000004020b1 <+113>: movlpd %xmm2,(%rsi,%rax,2)
0x00000000004020b6 <+118>: movhpd %xmm2,0x8(%rsi,%rax,2)
0x00000000004020bc <+124>: movlpd %xmm0,0x10(%rsi,%rax,2)
0x00000000004020c2 <+130>: movhpd %xmm0,0x18(%rsi,%rax,2)
0x00000000004020c8 <+136>: add $0x10,%rax
0x00000000004020cc <+140>: cmp %rcx,%rdx
0x00000000004020cf <+143>: ja 0x402098 <f_to_d+88>
0x00000000004020d1 <+145>: cmp %r9,%r8
0x00000000004020d4 <+148>: lea (%rsi,%r9,8),%rsi
0x00000000004020d8 <+152>: lea (%rdi,%r9,4),%rdi
0x00000000004020dc <+156>: je 0x40210d <f_to_d+205>
0x00000000004020de <+158>: mov %r9,%rdx
0x00000000004020e1 <+161>: mov %r9,%rax
0x00000000004020e4 <+164>: neg %rdx
0x00000000004020e7 <+167>: lea (%rsi,%rdx,8),%rcx
0x00000000004020eb <+171>: lea (%rdi,%rdx,4),%rdx
0x00000000004020ef <+175>: nop
0x00000000004020f0 <+176>: movss (%rdx,%rax,4),%xmm0
0x00000000004020f5 <+181>: cvtps2pd %xmm0,%xmm0
0x00000000004020f8 <+184>: movsd %xmm0,(%rcx,%rax,8)
0x00000000004020fd <+189>: add $0x1,%rax
0x0000000000402101 <+193>: cmp %rax,%r8
0x0000000000402104 <+196>: ja 0x4020f0 <f_to_d+176>
0x0000000000402106 <+198>: repz retq
0x0000000000402108 <+200>: xor %r9d,%r9d
0x000000000040210b <+203>: jmp 0x4020de <f_to_d+158>
0x000000000040210d <+205>: nopl (%rax)
0x0000000000402110 <+208>: retq

任何人都可以阐明 float->double 转换的幕后情况吗?也许如何编写才能更有效地组装出来?如果重要的话,我正在使用 gcc 4.6.3。

最佳答案

你所谓的“怪物”实际上看起来像automatically vectorized code .在这种技术开始发挥良好作用并在通用编译器中发挥作用之前,已经进行了大约 20 年的研究。

它可能不漂亮,但 GCC 实现者认为它对于长数组会更快。如果您的数组实际上并不长,或者如果您无法忍受这样的编译代码,请禁用该特定优化。用 -O2 编译应该可以(未尝试)。

关于c - 浮点到双转换 : why so many instructions?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12134606/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com