https://gcc.gnu.org/bugzilla/show_bug.cgi?id=17935
Andrew Pinski <pinskia at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |FIXED Target Milestone|--- |4.4.0 --- Comment #9 from Andrew Pinski <pinskia at gcc dot gnu.org> --- GCC 4.4.0 produces (which is like future versions of GCC): bar: movl 4(%esp), %eax testb $1, (%eax) je .L2 xorl %eax, %eax ret .L2: movl 8(%esp), %eax movb (%eax), %al xorl $1, %eax andl $1, %eax ret So GCC 4.5.0 and 4.6.0 produces: bar: movl 4(%esp), %eax testb $1, (%eax) jne .L3 movl 8(%esp), %eax testb $1, (%eax) sete %al ret .L3: xorl %eax, %eax ret Which is what we want. GCC 4.7-8.5.0 changed the testb to movb, xor and and: bar: .LFB0: movl 4(%esp), %eax testb $1, (%eax) jne .L3 movl 8(%esp), %eax movb (%eax), %al xorl $1, %eax andl $1, %eax ret .L3: xorl %eax, %eax ret GCC 9+ changes the xorl to a not: bar: movl 4(%esp), %eax testb $1, (%eax) jne .L3 movl 8(%esp), %eax movb (%eax), %al notl %eax andl $1, %eax ret .L3: xorl %eax, %eax ret So this was fixed back in GCC 4.4.0. I am not going to look what fixed it either.