~~~c #include <stdbool.h> typedef struct GNodeFlagsS { bool remake:1; bool childMade:1; bool force:1; bool doneWait:1; bool doneOrder:1; bool fromDepend:1; bool doneAllsrc:1; bool cycle:1; bool doneCycle:1; } GNodeFlags; bool GNodeFlags_IsNone(GNodeFlags flags) { return !flags.remake && !flags.childMade && !flags.force && !flags.doneWait && !flags.doneOrder && !flags.fromDepend && !flags.doneAllsrc && !flags.cycle && !flags.doneCycle; } ~~~ On x86_64, GCC 11.2 generates: ~~~asm GNodeFlags_IsNone(GNodeFlagsS): mov eax, edi and eax, 1 jne .L6 test dil, 2 jne .L1 mov eax, edi shr ax, 2 and eax, 1 jne .L6 test dil, 8 jne .L1 mov eax, edi shr ax, 4 and eax, 1 jne .L6 test dil, 32 jne .L1 mov eax, edi shr ax, 6 and eax, 1 jne .L6 test dil, dil js .L1 shr di, 8 mov eax, edi and eax, 1 xor eax, 1 ret .L6: xor eax, eax .L1: ret ~~~ ICC 2021.3.0 generates shorter code: ~~~asm test edi, 1 #18.10 jne ..B1.10 # Prob 50% #18.10 test edi, 2 #19.13 jne ..B1.10 # Prob 50% #19.13 test edi, 4 #20.13 jne ..B1.10 # Prob 50% #20.13 (and so on) ~~~ Many other compilers fail to see the potential for optimizing this code as well. Clang is better, it generates: ~~~asm GNodeFlags_IsNone(GNodeFlagsS): # @GNodeFlags_IsNone(GNodeFlagsS) test edi, 511 sete al ret ~~~
Mine for GCC 13. There is other bugs which are similar too.
Cool, thank you for taking this optimization. Just to give you a bit of background: I discovered this while converting some of the enum types in BSD Make to proper bitfields, which theoretically should be possible without affecting the generated code. https://github.com/NetBSD/src/blob/trunk/usr.bin/make/make.h It was interesting to play around with this code on https://godbolt.org/, seeing how differently the available compilers translate this simple code fragment. That's where the Intel assembler syntax comes from. :)
GCC 13.1 is being released, retargeting bugs to GCC 13.2.
GCC 13.2 is being released, retargeting bugs to GCC 13.3.
GCC 13.3 is being released, retargeting bugs to GCC 13.4.