I am taking a look at following two small functions:
int foo(int val) {
return val / 2;
}
int bar(int val) {
return val >> 1;
}
I expected compiler to generate the same code for both of them. However, here is the generated assembly at O3
foo(int): # @foo(int)
mov eax, edi
shr eax, 31
lea eax, [rax + rdi]
sar eax
ret
bar(int): # @bar(int)
sar edi
mov eax, edi
ret
Here is the godbolt link: https://godbolt.org/g/XrtdEY
I was wondering why there is difference between these two assemblies.
It's different assembly because division by 2 of a signed integer number must give a well-defined result (by the standard), even when faced with a negative input. The assembly has to account for that, and cannot just do a shift which may produce something "unexpected".
When you write an explicit shift, you acknowledge the looser contract the standard imposes on that operator. So the compiler has more leeway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With