如果我有以下 C++ 代码来比较两个 128 位无符号整数和内联 amd-64 asm:
struct uint128_t {
uint64_t lo, hi;
};
inline bool operator< (const uint128_t &a, const uint128_t &b)
{
uint64_t temp;
bool result;
__asm__(
"cmpq %3, %2;"
"sbbq %4, %1;"
"setc %0;"
: // outputs:
/*0*/"=r,1,2"(result),
/*1*/"=r,r,r"(temp)
: // inputs:
/*2*/"r,r,r"(a.lo),
/*3*/"emr,emr,emr"(b.lo),
/*4*/"emr,emr,emr"(b.hi),
"1"(a.hi));
return result;
}
然后它将被非常有效地内联,但有一个缺陷。返回值是通过值为 0 或 1 的通用寄存器的“接口”完成的。这增加了两个或三个不必要的额外指令,并减损了本来可以完全优化的比较操作。生成的代码将如下所示:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
setc al
movzx eax, al
test eax, eax
jnz is_lessthan
如果我使用带有“int”返回值的“sbb %0,%0”而不是带有“bool”返回值的“setc %0”,还有两条额外的指令:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
sbb eax, eax
test eax, eax
jnz is_lessthan
我想要的是这样的:
mov r10, [r14]
mov r11, [r14+8]
cmp r10, [r15]
sbb r11, [r15+8]
jc is_lessthan
GCC 扩展的内联汇编很棒,否则。但我希望它在各个方面都与内在函数一样好。我希望能够以 CPU 标志或标志的状态形式直接返回布尔值,而不必将其“渲染”到通用寄存器中。
这是可能的,还是必须修改甚至重构 GCC(以及英特尔 C++ 编译器,它也允许使用这种形式的内联汇编)才能实现?
另外,当我在做的时候——还有其他方法可以改进我的比较运算符吗?