Integer division / and modulo % operations are often used together in programming, sometimes even on the same operands and in subsequent lines. For example, the following C function, which is a simple function that sums the result of a / of 2 numbers with the result of their %, does just that:
int sum2digits(int x, int base) {
int n, m;
n = x / base;
m = x % base;
return n + m;
}
As I know, both / and % are performed by the same machine instruction (in x86). Say, if you perform a machine instruction for integer division (div or idiv) of two numbers, a and b, then afterwards the value of a / b will be stored in the register EAX and the remainder a % b in EDX.
I wondered whether the compiler takes advantage of this quality and took a look at the assembly code. It turns out that normal compilation with gcc doesn't optimize this:
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
This assembly code does 2 subsequent calls to idivl, but each time reads the result from another register (EAX for quotient, EDX for remainder).
However, compiling with the -O changes the picture:
mov %edi,%eax
mov %edi,%edx
sar $0x1f,%edx
idiv %esi
add %edx,%eax
retq
This code calls idiv only once, and uses its value for both computations.
Why isn't this kind of optimization a default? What is the use of calling div twice in a row? Can this optimization change the behaviour of a program in any way?
Also, and perhaps even more important, is there a way, as a programmer, to manually extract these 2 values (quotient and remainder) guaranteeing that only 1 integer division is performed by the CPU?