http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45903
--- Comment #1 from Zdenek Sojka <zsojka at seznam dot cz> 2010-10-06 10:03:48 UTC --- The first example should actually be: f64: mov al, DWORD PTR [esp+5] add al, DWORD PTR [esp+13] ret This happens to other operators, not just plus: uint8_t f64or(uint64_t a, uint64_t b) { return (a >> 8) | (b >> 8); } is compiled as: f64or: push ebx mov ecx, DWORD PTR [esp+8] mov ebx, DWORD PTR [esp+12] mov eax, DWORD PTR [esp+16] mov edx, DWORD PTR [esp+20] shrd ecx, ebx, 8 pop ebx shrd eax, edx, 8 or eax, ecx ret or when the shift is done after the operation: uint8_t f64or2(uint64_t a, uint64_t b) { return (a | b) >> 8; } results in: f64or2: mov ecx, DWORD PTR [esp+12] mov eax, DWORD PTR [esp+4] mov edx, DWORD PTR [esp+8] or eax, ecx mov ecx, DWORD PTR [esp+16] or edx, ecx shrd eax, edx, 8 ret When there is no shift, code is better: uint8_t f64or3(uint64_t a, uint64_t b) { return a | b; } is compiled as f64or3: mov eax, DWORD PTR [esp+12] or al, BYTE PTR [esp+4] ret