gpt4 book ai didi

gcc - 在 GCC 风格的扩展内联汇编中,是否可以输出 "virtualized" boolean 值,例如携带标志?

转载 作者:行者123 更新时间:2023-12-04 16:01:46 24 4
gpt4 key购买 nike

如果我有以下 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 的通用寄存器的“接口(interface)”完成的。这增加了两个或三个不必要的额外指令,并减损了本来可以完全优化的比较操作。生成的代码将如下所示:
    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 标志或标志的状态形式直接返回 boolean 值,而不必将其“渲染”到通用寄存器中。

这是可能的,还是必须修改甚至重构 GCC(以及英特尔 C++ 编译器,它也允许使用这种形式的内联汇编)才能实现?

另外,当我在做的时候——还有其他方法可以改进我的比较运算符吗?

最佳答案

差不多 7 年后,是的,gcc 终于添加了对“输出标志”的支持(在 6.1.0 中添加,于 2016 年 4 月发布)。详细文档为 here ,但简而言之,它看起来像这样:

/* Test if bit 0 is set in 'value' */
char a;

asm("bt $0, %1"
: "=@ccc" (a)
: "r" (value) );

if (a)
blah;

了解 =@ccc :输出约束(需要 = )的类型为 @cc后跟要使用的条件代码(在本例中为 c 以引用进位标志)。

好的,对于您的具体情况,这可能不再是问题(因为 gcc 现在支持直接比较 128 位数据类型),但是(目前)有 1,326 人查看了这个问题。显然对这个功能有些兴趣。

现在我个人更喜欢说 don't use inline asm at all的学派。 .但是,如果必须,是的,您可以(现在)“输出”标志。

FWIW。

关于gcc - 在 GCC 风格的扩展内联汇编中,是否可以输出 "virtualized" boolean 值,例如携带标志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2301556/

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