gpt4 book ai didi

gcc - 减去并检测下溢,最有效的方法? (带有 GCC 的 x86/64)

转载 作者:行者123 更新时间:2023-12-04 13:45:56 25 4
gpt4 key购买 nike

我正在使用 GCC 4.8.1 来编译 C 代码,我需要检测 x86/64 架构上的减法是否发生下溢。两者都是未签名的。我知道汇编很容易,但我想知道我是否可以在 C 代码中完成并让 GCC 以某种方式对其进行优化,因为我找不到它。这是一个非常常用的函数(或低级,是这个术语吗?)所以我需要它是高效的,但是 GCC 似乎太笨了,无法识别这个简单的操作?我尝试了很多方法在 C 中给它提示,但它总是使用两个寄存器,而不仅仅是一个子跳转和一个条件跳转。老实说,看到这么多次编写如此愚蠢的代码(函数被调用很多),我很生气。

我在 C 中的最佳方法似乎如下:

if((a-=b)+b < b) {
// underflow here
}

基本上,从a中减去b,如果结果下溢检测到它并做一些条件处理(这与a的值无关,例如,它会带来错误等)。

GCC 似乎太愚蠢了,无法将上述内容简化为子跳转和条件跳转,相信我,我在 C 代码中尝试了很多方法,并尝试了很多命令行选项(当然包括 -O3 和 -Os)。 GCC 的作用是这样的(英特尔语法汇编):
mov rax, rcx  ; 'a' is in rcx
sub rcx, rdx ; 'b' is in rdx
cmp rax, rdx ; useless comparison since sub already sets flags
jc underflow

不用说以上是愚蠢的,当它需要的是:
sub rcx, rdx
jc underflow

这太烦人了,因为 GCC 确实理解 sub 以这种方式修改标志,因为如果我将它类型转换为“int”,它将生成完全上面的内容,除了它使用“js”,它是带符号的跳转,而不是进位,它不会如果无符号值差异足够高以设置高位,则工作。尽管如此,它表明它知道影响这些标志的子指令。

现在,也许我应该放弃尝试让 GCC 正确优化它并使用我没有问题的内联汇编来完成它。不幸的是,这需要“asm goto”,因为我需要一个有条件的 JUMP,而 asm goto 对于输出不是很有效,因为它是不稳定的。

我尝试了一些东西,但我不知道使用它是否“安全”。由于某种原因,asm goto 不能有输出。我不想让它将所有寄存器刷新到内存,这会扼杀我正在做的整个点,这就是效率。但是,如果我使用空的 asm 语句,并且在它之前和之后将输出设置为 'a' 变量,这会起作用吗并且安全吗?这是我的宏:
#define subchk(a,b,g) { typeof(a) _a=a; \
asm("":"+rm"(_a)::"cc"); \
asm goto("sub %1,%0;jc %l2"::"r,m,r"(_a),"r,r,m"(b):"cc":g); \
asm("":"+rm"(_a)::"cc"); }

并像这样使用它:
subchk(a,b,underflow)
// normal code with no underflow
// ...

underflow:
// underflow occured here

这有点难看,但效果很好。在我的测试场景中,它编译得很好,没有 volatile 开销(将寄存器刷新到内存)而不会产生任何不好的东西,看起来它工作正常,但这只是一个有限的测试,我不可能在我使用这个函数的任何地方测试它/macro 正如我所说,它被大量使用,所以我想知道是否有人知识渊博,上述构造是否存在不安全之处?

特别是,如果发生下溢,则不需要 'a' 的值,因此请记住,我的内联 asm 宏是否会发生任何副作用或不安全的事情?如果不是,我会毫无问题地使用它,直到他们优化编译器,这样我就可以在我猜测之后将其替换回来。

请不要把这变成关于过早优化或什么不是的辩论,继续讨论这个问题,我完全意识到这一点,所以谢谢你。

最佳答案

我可能会错过一些明显的东西,但为什么这不好呢?

extern void underflow(void) __attribute__((noreturn));
unsigned foo(unsigned a, unsigned b)
{
unsigned r = a - b;
if (r > a)
{
underflow();
}
return r;
}

我已经检查过,gcc 将其优化为您想要的:
foo:
movl %edi, %eax
subl %esi, %eax
jb .L6
rep
ret
.L6:
pushq %rax
call underflow

当然,您可以根据需要处理下溢,我刚刚这样做是为了保持 asm 简单。

关于gcc - 减去并检测下溢,最有效的方法? (带有 GCC 的 x86/64),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24958469/

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