- 第一章 CPU 简介
- 第二章 Hello,world!
- 第三章 函数开始和结束
- 第四章 栈
- Chapter 5 printf() 与参数处理
- Chapter 6 scanf()
- CHAPER7 访问传递参数
- Chapter 8 一个或者多个字的返回值
- Chapter 9 指针
- Chapter 10 条件跳转
- 第 11 章 选择结构 switch()/case/default
- 第 12 章 循环结构
- 第 13 章 strlen()
- Chapter 14 Division by 9
- chapter 15 用 FPU 工作
- Chapter 16 数组
- Chapter 17 位域
- 第 18 章 结构体
- 19 章 联合体
- 第二十章 函数指针
- 第 21 章 在 32 位环境中的 64 位值
- 第二十二章 SIMD
- 23 章 64 位化
- 24 章 使用 x64 下的 SIMD 来处理浮点数
- 25 章 温度转换
- 26 章 C99 的限制
- 27 章 内联函数
- 第 28 章 得到不正确反汇编结果
- 第 29 章 花指令
- 第 30 章 16 位 Windows
- 第 31 章 类
- 三十二 ostream
- 34.2.2 MSVC
- 34.2.3 C++ 11 std::forward_list
- 34.3 std::vector
- 34.4 std::map and std::set
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
24 章 使用 x64 下的 SIMD 来处理浮点数
当然,在增加了 x64 扩展这个特性之后,FPU 在 x86 兼容处理器中还是存在的。但是同事,SIMD 扩展(SSE, SSE2 等)已经有了,他们也可以处理浮点数。数字格式依然相同(使用 IEEE754 标准)。
所以,x86-64 编译器通常都使用 SIMD 指令。可以说这是一个好消息,因为这让我们可以更容易的使用他们。 24.1 简单的例子
#!cpp
double f (double a, double b)
{
return a/3.14 + b*4.1;
};
清单 24.1: MSFC 2012 x64 /Ox
#!bash
__real@4010666666666666 DQ 04010666666666666r ; 4.1
__real@40091eb851eb851f DQ 040091eb851eb851fr ; 3.14
a$ = 8
b$ = 16
f PROC
divsd xmm0, QWORD PTR __real@40091eb851eb851f
mulsd xmm1, QWORD PTR __real@4010666666666666
addsd xmm0, xmm1
ret 0
f ENDP
输入的浮点数被传入了 XMM0-XMM3 寄存器,其他的通过栈来传递。 a 被传入了 XMM0,b 则是通过 XMM1。 XMM 寄存器是 128 位的(可以参考 SIMD22 一节),但是我们的类型是 double 型的,也就意味着只有一半的寄存器会被使用。
DIVSD 是一个 SSE 指令,意思是“Divide Scalar Double-Precision Floating-Point Values”(除以标量双精度浮点数值),它只是把一个 double 除以另一个 double,然后把结果存在操作符的低一半位中。 常量会被编译器以 IEEE754 格式提前编码。 MULSD 和 ADDSD 也是类似的,只不过一个是乘法,一个是加法。 函数处理 double 的结果将保存在 XMM0 寄存器中。
这是无优化的 MSVC 编译器的结果:
清单 24.2: MSVC 2012 x64
#!bash
__real@4010666666666666 DQ 04010666666666666r ; 4.1
__real@40091eb851eb851f DQ 040091eb851eb851fr ; 3.14
a$ = 8
b$ = 16
f PROC
movsdx QWORD PTR [rsp+16], xmm1
movsdx QWORD PTR [rsp+8], xmm0
movsdx xmm0, QWORD PTR a$[rsp]
divsd xmm0, QWORD PTR __real@40091eb851eb851f
movsdx xmm1, QWORD PTR b$[rsp]
mulsd xmm1, QWORD PTR __real@4010666666666666
addsd xmm0, xmm1
ret 0
f ENDP
有一些繁杂,输入参数保存在“shadow space”(影子空间,7.2.1 节),但是只有低一半的寄存器,也即只有 64 位存了这个 double 的值。
GCC 编译器生成了几乎一样的代码。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论