编译器求余优化

Posted 不会写代码的丝丽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器求余优化相关的知识,希望对你有一定的参考价值。

前言

我们知道求余也是需要调用div汇编指令,但是div指令周期过长编译器往往会进行算式优化,进而避免调用div指令。

被除数为2的倍数

int main(int argc, char* args[])

	return   argc%8;

为了看懂这个算式我们首先明白一些基础逻辑:
我们除以2的倍数时可以进行位移计算,所以对于余数来说也是同理论优化思想。

我们以 58 % 8 = 2为例来说明

二进制:
58 -> 0011 1010
8 -> 0000 1000
2 -> 0000 0010

这个公式在无符号中是正确的如下面的汇编代码


对应的源码

我们只需要对位移数进行and计算即可得到结果。

对于负数除法我们需要进行以下优化处理:

tip:上面图58>>3 错误 改为 -15>>3

上面算式可以用在余数不为的情况,如果为0 前面补1明显将会带来错误。
编译器才用了一种取巧的做法进而避免分支判断,对移出来的二进制先减一,然后补全前面1,最后在加上1。

上面额外多出的两个步骤对于余数为0颇为有用如下所示:

根据前面的理论现在应该可以看懂以下汇编含义

非除数为2求余

int main( int argc, char* args[])


	return  argc % 7;
 

以上是关于编译器求余优化的主要内容,如果未能解决你的问题,请参考以下文章

java求余的数然后恢复

说说编译器是否会对已知结果的运算式做出优化?(老物)

MATLAB中有没有求余运算符?

mod的运算规则是啥?

php求余运算结果,反推出来之前的数据。比如x%69返回结果是584,x怎么才能推出来结果?

取模和求余的区别