So someone on a forum asked why this C function (which I added const
and restrict
to, just in case):
void foo(int *const restrict dest, const int *const restrict source) {
*dest = (*source != -1) ? *source : *dest;
}
generates this Assembly, both with the latest gcc and clang compiler, and using -Os
to optimize for size on godbolt:
foo:
mov eax, dword ptr [rsi]
cmp eax, -1
jne .LBB0_2
mov eax, dword ptr [rdi]
.LBB0_2:
mov dword ptr [rdi], eax
ret
This seemingly identical function however generates one less instruction on godbolt:
void foo(int *const restrict dest, const int *const restrict source) {
if (*source != -1) {
*dest = *source;
}
}
foo:
mov eax, dword ptr [rsi]
cmp eax, -1
je .LBB0_2
mov dword ptr [rdi], eax
.LBB0_2:
ret
Maybe I’m missing something, or maybe I’m underestimating how tricky it is for compilers to optimize this, but I would have expected the compiler to detect that *dest = *dest
can’t have any side-effects, since I didn’t mark it volatile
, and is thus allowed to optimize the ternary to the if-statement version. I’ve found other Stack Overflow answers to similar questions that often boil it down to GCC having an edge over Clang in one case, and vice versa, but it seems strange that neither seems to optimize this case to me.