Does gcc/g++ have flags to enable or disable arithmetic optimisations, e.g. where a+a+...+a
is replaced by n*a
when a
is an integer? In particular, can this be disabled when using -O2
or -O3
?
In the example below even with -O0
the add operations are replaced by a single multiplication:
$ 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
Even disabling all the flags used in -O0
(see g++ -c -Q -O0 --help=optimizers | grep enabled
) still produces the imul
operation.
When adding loops, it requires -O1
to simplify the repeated addition to a single multiplication:
$ 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
I.e. -O1
has moved the sum += a;
outside the loop and replaced it by a single multiplication. With -O2
it will also remove the dead loop.
I'm just asking out of interest as I was trying to time some basic integer operations and noticed that the compiler optimised my loops away and I couldn't find any flags to disable this.
-O0
, and we know it is not enough for you. – Sloopasm volatile("" : "=r"(a) : : "memory");
? – Aweatherasm
keyword supported by gcc (look for documentation online) and write an explicit assembler section for your sum. I'm not sure about it, and that's the reason why I cannot write an answer about it, but I'm confident it could work. Since I'm not an Intel asm expert, I would start writing a simple a+b sum program, open the asm and extend it in order to have the a*22 sum. Then I would put it into the asm section. – Sloopadd
,imul
,idiv
operations etc, and I know there are some good manuals online like agner.org/optimize/instruction_tables.pdf but it's always nice to replicate locally :) – Amalgam