gpt4 book ai didi

c - 优化后续调用整数除法和取模(余数)

转载 作者:太空狗 更新时间:2023-10-29 15:00:56 27 4
gpt4 key购买 nike

整数除法 / 和取模 % 运算在编程中经常一起使用,有时甚至在相同的操作数和后续行中使用。例如,下面的 C 函数是一个简单的函数,它将 2 个数字的 / 的结果与其 % 的结果相加,就是这样做的:

int sum2digits(int x, int base) {
int n, m;
n = x / base;
m = x % base;
return n + m;
}

据我所知,/% 都是由相同的机器指令执行的(在 x86 中)。比方说,如果您对两个数字 ab 执行整数除法(dividiv)的机器指令>,然后 a/b 的值将存储在寄存器 EAX 中,余数 a % b 存储在 EDX 中。
我想知道编译器是否利用了这种质量并查看了汇编代码。事实证明,使用 gcc 进行正常编译并不能优化这一点:

push   %rbp
mov %rsp,%rbp
mov %edi,-0x14(%rbp)
mov %esi,-0x18(%rbp)
mov -0x14(%rbp),%eax
mov %eax,%edx
sar $0x1f,%edx
idivl -0x18(%rbp)
mov %eax,-0x8(%rbp)
mov -0x14(%rbp),%eax
mov %eax,%edx
sar $0x1f,%edx
idivl -0x18(%rbp)
mov %edx,-0x4(%rbp)
mov -0x4(%rbp),%eax
mov -0x8(%rbp),%edx
add %edx,%eax
pop %rbp
retq

此汇编代码对 idivl 进行了 2 次后续调用,但每次都从另一个寄存器读取结果(EAX 表示商,EDX 表示余数)。但是,使用 -O 进行编译会改变图片:

mov    %edi,%eax
mov %edi,%edx
sar $0x1f,%edx
idiv %esi
add %edx,%eax
retq

此代码仅调用一次 idiv,并在两次计算中使用它的值。
为什么这种优化不是默认的?连续两次调用div有什么用?这种优化能否以任何方式改变程序的行为?
此外,也许更重要的是,作为程序员,是否有一种方法可以手动提取这 2 个值(商和余数)以保证 CPU 仅执行 1 次整数除法?

最佳答案

Why isn't this kind of optimization a default?

如果编译器和优化器是完美的并且调试器可以对代码进行逆向工程,那么优化将成为普遍的默认设置。但是编译器并不总是生成正确的代码,优化器并不总是保留语义,调试器也不能总是找出任何给定指令与优化程序的哪些部分相关。看起来您的编译器安装了默认选项,以确保绝对安全和调试简单。

is there a way to manually extract these 2 values (quotient and remainder) guaranteeing that only 1 integer division is performed by the CPU?

现在最好的方法就是你所做的:向编译器询问优化代码。 div 例程是从除法运算符的结果被定义为负数的日子以来的遗留物,并且优化编译非常缓慢以至于识别这样的事情最好手动完成。

关于c - 优化后续调用整数除法和取模(余数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15912621/

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