https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84982
Bug ID: 84982 Summary: logically inverting bools into local array results in bitwise negation Product: gcc Version: 8.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: gcc at basnieuwenhuizen dot nl Target Milestone: --- Example program: #include <stdbool.h> struct T { bool a; bool b; }; extern void t_dummy(bool *flags); void t(struct T *t) { bool flags[2]; // These two logical nots get combined and converted to a single bitwise not. // of course a bitwise not does not give the expected results. flags[0] = !t->a; flags[1] = !t->b; t_dummy(flags); } output with gcc -v -save-temps -c -o /tmp/test.o /tmp/test.c -O3: 0000000000000000 <t>: 0: 48 83 ec 18 sub $0x18,%rsp 4: 0f b7 07 movzwl (%rdi),%eax 7: 48 8d 7c 24 0e lea 0xe(%rsp),%rdi c: f7 d0 not %eax e: 66 89 44 24 0e mov %ax,0xe(%rsp) 13: e8 00 00 00 00 callq 18 <t+0x18> 18: 48 83 c4 18 add $0x18,%rsp 1c: c3 retq The logical negation gets turned into a bitwise negation during optimization. As a result if the input contains 1 the output contains 254 instead of zero. GCC seems to assume values of {0,1} otherwise, as the non-merged not is a xor with 1. This happens on svn trunk as of today (8.0.1 20180319 (experimental)), the 8.0 provided by fedora (8.0.1 20180222 (Red Hat 8.0.1-0.16)), but does not happen on the arch gcc version (7.3.1 20180312). If I figure out how to bisect with SVN I might have time to bisect this later this week. It seems that if I make the flags array an argument instead of a local + a function call using it, the merging goes away and with it the problem. Apologies if this the wrong component. I have no idea which optimization layer of GCC would cause this, and hence no idea where to route it to.