GCC does a better job folding operations involving plain Booleans than it does with bool bit-fields. The example below shows that in f() the return statement is folded to zero while in g() it's not. This is behind a class of -Wmaybe-uninitialized warnings. $ cat z.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout z.c struct A { _Bool i, j; }; _Bool f (struct A a) { if (a.i) a.j = 0; else a.j = a.i; return a.j; // folded to 0 } struct B { _Bool i: 1, j: 1; }; _Bool g (struct B b) { if (b.i) b.j = 0; else b.j = b.i; return b.j; // not folded } ;; Function f (f, funcdef_no=0, decl_uid=1946, cgraph_uid=1, symbol_order=0) _Bool f (struct A a) { <bb 2> [local count: 1073741824]: return 0; } ;; Function g (g, funcdef_no=1, decl_uid=1953, cgraph_uid=2, symbol_order=1) Removing basic block 5 _Bool g (struct B b) { _Bool b$j; unsigned char _1; unsigned char _2; _Bool _3; <bb 2> [local count: 1073741824]: _1 = VIEW_CONVERT_EXPR<unsigned char>(b); _2 = _1 & 1; if (_2 != 0) goto <bb 4>; [50.00%] else goto <bb 3>; [50.00%] <bb 3> [local count: 536870913]: _3 = b.i; <bb 4> [local count: 1073741824]: # b$j_5 = PHI <0(2), _3(3)> return b$j_5; }
This comes down to lowering bitfields too soon. my bet it will happen even integer bitfields will have a problem.
Bisection points to r225825 as the revision where GCC started to fail to fold the code in g().
This only seems to affect C _Bool bit-fields and not C++ bool.
(In reply to Andrew Pinski from comment #1) > This comes down to lowering bitfields too soon. > my bet it will happen even integer bitfields will have a problem. Yes, unsigned bit-fields suffer the same problem but unlike for _Bool, GCC never emitted optimal code for those for this test case.
The main issue is optimize_bit_field_compare in fold-const.c which produces during GENERIC folding in .005t.original: if ((BIT_FIELD_REF <b, 8, 0> & 1) != 0) { b.j = 0; } else { b.j = b.i; } return b.j; that's premature in this place. For f() it also takes until DOM3 to do the folding unless you disable SRA which then makes EVRP recognize the second store as a.j = 0. With SRA we fail to derive ranges for a_10 in a_10 = MEM <unsigned char> [(struct A *)&a]; a$1_11 = MEM <unsigned char> [(struct A *)&a + 1B]; _1 = VIEW_CONVERT_EXPR<_Bool>(a_10); if (_1 != 0) goto <bb 4>; [INV] else goto <bb 3>; [INV] <bb 3> : <bb 4> : # a$1_9 = PHI <0(2), a_10(3)> _7 = VIEW_CONVERT_EXPR<_Bool>(a$1_9); thus we're missing looking through VIEW_CONVERT_EXPR in register_assert_for. Amending that would eventually also allow optimizing the prematurely folded vairant.
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
GCC 9 branch is being closed
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
Another simple example: #include <cstdint> struct SomeClass { bool cfg1 : 1; bool cfg2 : 1; bool cfg3 : 1; bool check() const noexcept { return cfg1 || cfg2 || cfg3; } }; bool check(const SomeClass& rt) { return rt.check(); } Emits: check(SomeClass const&): movzx edx, BYTE PTR [rdi] mov eax, edx and eax, 1 jne .L1 mov eax, edx shr al and eax, 1 je .L4 .L1: ret .L4: mov eax, edx shr al, 2 and eax, 1 ret While it should: check(SomeClass const&): test byte ptr [rdi], 7 setne al ret
GCC 10 branch is being closed.
(In reply to Martin Sebor from comment #2) > Bisection points to r225825 as the revision where GCC started to fail to > fold the code in g(). the fold-const didn't check `types_match (type, TREE_TYPE (@0))` but rather just did the equivalent to: (simplify (ne @0 integer_zerop@1) (if (TREE_CODE (TREE_TYPE (@0)) == BOOLEAN_TYPE) (non_lvalue (convert @0)))) While match now does not do the convert and checks the types_match check instead.
GCC 11 branch is being closed.
The main bug (and known regression) has been fixed on the trunk. However the additional testcase in c#9 has not. Given c#9 was unaffected by the changes on the trunk and we have no sense if c#9 is a regression or not, I've extracted that testcase into a new bug (bz118267) and I'm adjusting the regression markers on this bug.
GCC 12 branch is being closed.
Given we don't generally backport missed optimization bugfixes to release branches, I'm closing this as fixed. The one outstanding issue was already pulled out into a distinct BZ.