--- demo.c --- int ispowerof2(unsigned long long argument) { return (argument != 0) && ((argument & argument - 1) == 0); } --- EOF ---
GCC 12.2 gcc -m32 -O3 https://gcc.godbolt.org/z/YWP4zb8jd ispowerof2(unsigned long long): push edi # three registers clobbered push esi # without need, and three push ebx # superfluous memory writes mov edi, DWORD PTR [esp+20] -> mov ecx, [esp+4] mov esi, DWORD PTR [esp+16] -> mov edx, [esp+8] mov eax, edi -> mov eax, ecx or eax, esi -> or eax, edx je .L5 -> jz .L0 mov eax, esi # superfluous mov edx, edi # superfluous add eax, -1 -> add ecx, -1 adc edx, -1 -> adc edx, -1 mov ecx, eax # shell game mov eax, esi # shell game mov ebx, edx # shell game mov edx, edi # shell game and eax, ecx -> and ecx, [esp+4] xor ecx, ecx -> xor eax, eax and edx, ebx -> and edx, [esp+8] pop ebx # superfluous pop esi # superfluous or eax, edx -> or ecx, edx pop edi # superfluous sete cl -> setz al mov eax, ecx # shell game ret .L0: -> ret .L5: # eax is 0 here! xor ecx, ecx # superfluous pop ebx # superfluous pop esi # superfluous mov eax, ecx # superfluous pop edi # superfluous ret # superfluous OUCH: 19 (in words: NINETEEN) superfluous instructions out of 32, despite -O3, 3 registers clobbered without need and reason, resulting in 3 superfluous memory writes GCC 12.3 generates the same BRAINDEAD code! GCC 13.3 gcc -m32 -O3 https://gcc.godbolt.org/z/Ge7q4Tv9M ispowerof2(unsigned long long): push esi # two registers clobbered without need, push ebx # two superfluous memory writes mov ecx, DWORD PTR [esp+12] -> mov ecx, [esp+4] mov ebx, DWORD PTR [esp+16] -> mov edx, [esp+8] mov eax, ecx -> mov eax, ecx or eax, ebx -> or eax, edx je .L5 -> jz .L0 xor eax, eax mov eax, ecx # superfluous mov edx, ebx # superfluous add eax, -1 -> add ecx, -1 adc edx, -1 -> adc edx, -1 and eax, ecx -> and ecx, [esp+4] and edx, ebx -> and edx, [esp+8] pop ebx # superfluous or eax, edx -> or ecx, edx sete al -> setz al movzx eax, al # superfluous: see xor added above mov esi, eax # shell game mov eax, esi # shell game pop esi # superfluous ret .L0: -> ret .L5: # eax is 0 here! xor esi, esi # superfluous pop ebx # superfluous mov eax, esi # superfluous pop esi # superfluous ret # superfluous OUCH: 13 (in words: THIRTEEN) superfluous instructions out of 26, despite -O3, 2 registers clobbered without need and reason, resulting in 2 superfluous memory writes It's e REAL shame how bad GCC's code generator is! Stefan