Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

replace divide by shift

Tags:

c++

assembly

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.

like image 481
skgbanga Avatar asked Jun 09 '26 16:06

skgbanga


1 Answers

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.

like image 56
StoryTeller - Unslander Monica Avatar answered Jun 12 '26 11:06

StoryTeller - Unslander Monica