So now let's have a look at what the compiler does (gcc-6.2 on x86-64, Linux).kbhearn wrote:well if the goal was to remove the union and avoid umpteen bajillion casts, the tradeoff is doing a manual sign extension and perhaps that'd make it slower (maybe the compiler would recognise what you're doing though and it'd be the same) though i'd argue more readable...
SF's current code using a union for casting (cleaned up by me for readability):
Code: Select all
_Z10make_scoreii:
sall $16, %esi
leal (%rsi,%rdi), %eax
ret
_Z8eg_value5Score:
leal 32768(%rdi), %eax
sarl $16, %eax
ret
_Z8mg_value5Score:
movswl %di, %eax
retYour manual sign-shift code:
Code: Select all
_Z10make_scorejj:
sall $16, %esi
leal (%rsi,%rdi), %eax
ret
_Z8eg_Value5Score:
leal -2147450880(%rdi), %eax
shrl $16, %eax
subl $32768, %eax
ret
_Z8mg_Value5Score:
movswl %di, %eax
retOnly eg_value() has one instruction extra.
The direct casting method:
Code: Select all
_Z10make_scoreii:
sall $16, %esi
leal (%rsi,%rdi), %eax
ret
_Z8eg_value5Score:
leal 32768(%rdi), %eax
sarl $16, %eax
ret
_Z8mg_value5Score:
movswl %di, %eax
retOliver's code:
Code: Select all
_Z10make_scoreii:
sall $16, %esi
leal (%rsi,%rdi), %eax
ret
_Z8eg_value5Score:
leal 32768(%rdi), %eax
sarl $16, %eax
ret
_Z8mg_value5Score:
leal 32768(%rdi), %eax
movzwl %ax, %eax
subl $32768, %eax
retmg_value() has two instructions extra.
Once you start inlining these functions the different implementations seem to have different effects on how the rest of the code is compiled, but that is beyond the programmer's control and will have to be ignored.