很久以前,我使用这个简单的x86汇编程序技巧来获得0或1,这是浮点数比较的结果:
fld [value1]
fcom [value2]
fnstsw ax
mov al, ah
and eax, 1如果比较结果仅影响从2组值中选择一个值,则此技巧允许避免分支。它在奔腾时代很快,现在它可能没有那么快,但谁知道。
现在我主要使用C++,使用Intel C++编译器或GCC C++编译器进行编译。
谁能帮我把这段代码改写成2个内置的汇编器版本(英特尔和GCC)?
所需的函数原型是:内联int compareDoublesIndexed( const double value1,const double value2 ){.}
也许使用SSE2操作更有效率。你的观点?
我试过这个:
__asm__(
"fcomq %2, %0\n"
"fnstsw %ax\n"
"fsubq %2, %0\n"
"andq $L80, %eax\n"
"shrq $5, %eax\n"
"fmulq (%3,%eax), %0\n"
: "=f" (penv)
: "0" (penv), "F" (env), "r" (c)
: "eax" );但是我在Intel C++编译器中得到了错误:浮点输出约束必须指定一个寄存器。
发布于 2014-03-09 13:17:56
正如你提到的,奔腾时代以来的情况发生了变化:
因此,首先检查编译器生成了什么,您可能会感到惊喜。我在下面的代码中尝试了g++和-O3
fcmp.cpp:
int compareDoublesIndexed( const double value1, const double value2 ) {
return value1 < value2 ? 1 : 0;
}这就是编译器生成的内容。
0000000000400690 <_Z21compareDoublesIndexeddd>:
400690: 31 c0 xor %eax,%eax
400692: 66 0f 2e c8 ucomisd %xmm0,%xmm1
400696: 0f 97 c0 seta %al
400699: c3 retq 这就是它的意思
xor %eax,%eax ; EAX = 0
ucomisd %xmm0,%xmm1 ; compare value2 (in %xmm1) with value1 (in %xmm0)
seta %al ; AL = value2 > value1 ? 1 : 0因此,编译器通过使用seta指令避免了条件分支(如果结果在上面,则将字节设置为'1‘,否则设置为'0’)。
https://stackoverflow.com/questions/22279619
复制相似问题