本文介绍了为什么编译器生成编译的程序集code额外sqrts的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我试图来分析它需要使用下面这个简单的C code,其中readTSC()是一个函数读取CPU的周期计数器来计算平方根的时间。
双总和= 0.0;
INT I;
TM = readTSC();
对于(i = 0; I< N;我++)
总和+ =开方((双)一);
TM = readTSC() - TM;
的printf(%LLD钟总\\ n,TM);
的printf(%15.6e \\ n,总和);
不过,我用打印出来组装code
GCC -S timing.c -o timing.s
英特尔机上,结果(如下所示)是令人惊讶的
为什么有两个sqrts在装配code与一个使用 sqrtsd
指令和其他使用函数调用?是这涉及到循环展开,并试图在一次迭代执行两个sqrts?
和如何理解行
ucomisd%XMM0,%XMM0
为什么它比较%XMM0
来自己?
// ----------------的for循环开始----------------
调用readTSC
MOVQ%RAX,-32(RBP%)
MOVL $ 0 -4(RBP%)
JMP .L4
.L6:
cvtsi2sd -4(RBP%),%将xmm1
// 1.使用sqrtsd指令
sqrtsd%将xmm1,%XMM0
ucomisd%XMM0,%XMM0
JP .L8
JE .L5
.L8:
MOVAPD%将xmm1,%XMM0
// 2.采用C调用功能可按
调用sqrt
.L5:
MOVSD -16(RBP%),%将xmm1
addsd%将xmm1,%XMM0
MOVSD%XMM0,-16(RBP%)
ADDL $ 1,-4(RBP%)
.L4:
MOVL -4(RBP%),%EAX
CMPL -36(RBP%),%EAX
JL .L6
结束// ----------------循环----------------
调用readTSC
解决方案
它使用库开方
错误处理功能。作为一种优化,它首先试图通过内联 sqrtsd
指令来执行的平方根,然后利用检查结果对自身的 ucomisd
指令用于设置标志如下:
In particular, comparing a QNaN
to itself will return UNORDERED
, which is what you will get if you try to take the square root of a negative number. This is covered by the jp
branch. The je
check is just paranoia, checking for exact equality.
Also note that gcc has a -ffast-math
option which will sacrifice this error handling for speed.
这篇关于为什么编译器生成编译的程序集code额外sqrts的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!