gcc / g ++是否有用于启用或禁用算术优化的标志,例如a+a+...+a
是整数时,n*a
被a
替换的地方?特别是在使用-O2
或-O3
时可以禁用此功能吗?
在下面的示例中,即使是-O0
,加法运算也会被一个乘法代替:
$ cat add1.cpp
unsigned int multiply_by_22(unsigned int a)
{
return a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;
}
$ g++ -S -masm=intel -O0 add1.cpp
$ cat add1.s
...
imul eax, edi, 22
即使禁用-O0
(请参阅g++ -c -Q -O0 --help=optimizers | grep enabled
)中使用的所有标志仍会产生imul
操作。
[添加循环时,它需要-O1
来简化对单个乘法的重复加法:
$ cat add2.cpp
unsigned int multiply(unsigned int a, unsigned int b)
{
unsigned int sum=0;
for(unsigned int i=0; i<b; i++)
sum += a;
return sum;
}
$ g++ -S -masm=intel -O1 add2.cpp
$ cat add2.s
...
mov eax, 0
.L3:
add eax, 1
cmp esi, eax
jne .L3
imul eax, edi
ret
即-O1
已将sum += a;
移动到了循环之外,并用一个乘法代替了它。使用-O2
,它也将消除死循环。
[我只是想让一些基本的整数运算计时而没有兴趣,并且注意到编译器优化了我的循环,并且我找不到任何标志来禁用此功能。
我不知道这样的编译器标志。
也许您可以尝试使用volatile
作为替代:
unsigned int multiply_by_22(volatile unsigned int a)
{
return a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a;
}
使用-O0,您将得到:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov edx, DWORD PTR [rbp-4]
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
mov eax, DWORD PTR [rbp-4]
add edx, eax
etc...
似乎也适用于-O2:https://godbolt.org/z/Bk2b6Z