[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 --- Comment #8 from Roland Illig --- When I compile the attached code with "ARM GCC 10.5.0" and "-O2 -fPIE -ftrapv" on godbolt.org, the generated code is correct (you can search for "#327" in the output and then go back one branch). The code generated by godbolt.org "ARM GCC 11.4.0" with "-O2 -fPIE -ftrapv" looks good as well. So it could also be that the NetBSD version of GCC is missing a bug-fix or two.
[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 --- Comment #7 from Roland Illig --- Created attachment 55612 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55612=edit Preprocessed source from comment 5
[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 Roland Illig changed: What|Removed |Added Attachment #55598|0 |1 is obsolete|| Attachment #55599|0 |1 is obsolete|| --- Comment #6 from Roland Illig --- Created attachment 55611 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55611=edit Precompiled source from comment 5
[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 --- Comment #5 from Roland Illig --- Sorry for the confusing description. Let me try again. NetBSD lint includes a yacc parser for C code. This parser contains the rules 'block_item_list' and 'block_item': https://github.com/NetBSD/src/blob/7ebcd1679b455e619909ec9c128e8ad7f103ded9/usr.bin/xlint/lint1/cgram.y#L1804 > block_item_list: /* C99 6.8.2 */ > block_item > | block_item_list block_item { > if ($1 && !$2) > /* declarations after statements is a C99 feature */ > c99ism(327); > $$ = $1 || $2; > } The rule 'block_item' remembers in 'y_seen_statement' whether the item was a statement, so that the parser rule 'block_item_list' can warn in C90 mode. In another part of the parser, the rule 'gcc_attribute' handles the keyword 'const', by accessing 'y_type_qualifiers.tq_const', which on 2023-07-15 was a _Bool bit-field member in 'struct type_qualifiers'. https://github.com/NetBSD/src/blob/7ebcd1679b455e619909ec9c128e8ad7f103ded9/usr.bin/xlint/lint1/cgram.y#L2197 > gcc_attribute: > | type_qualifier { > if (!$1.tq_const) > yyerror("Bad attribute"); > } On big-endian arm and powerpc, the code that GCC 10.5.0 generates for the 'block_item_list' parser rule depends on whether the 'gcc_attribute' parser rule accesses a bit-field member or not. This does not make sense to me, as I expect the parser rules to be independent. When I compile this parser on arm with -O2 and run lint in C90 mode, it not only warns about declarations after statements, but also about statements after statements. $ gcc -O2 -ftrapv -fPIE -std=gnu99 -S cgram.c -o cgram.casmv -fverbose-asm The code that is generated for the condition '$1 && !$2' is: > @ cgram.y:1802: if ($1 && !$2) > ldr r6, .L580+796 > add r6, pc, r6 > ldr r4, [r6, #20] > ldrbr3, [r4, #-8] @ $1.y_seen_statement > cmp r3, #0 > beq .L368 > @ cgram.y:550: $$ = build_unary($2 == INC ? INCAFT : DECAFT, $3, $1); > ldrbr3, [r4] > @ cgram.y:1802: > lsrsr3, r3, #7 @ $2.y_type_qualifiers.tq_const > beq .L562 (Annotations hand-edited by me.) Two strange things happen here: 1. The code from cgram.y:550 is completely unrelated, so it should not have been mentioned here. The 'ldrb' is correct, so maybe it's just the attribution that is wrong. 2. The expressions '$1' and '$2' both have type _Bool. Nevertheless, the second bool is accessed as if it were a bit-field. Due to this access, no matter whether '$2 as bool' is 1 or 0, the the expression '($2 as bit-field) >> 7' always evaluates to 0, so the condition '$1 && !$2' evaluates to true, which results in the additional warnings from lint. Instead of lsrs, GCC should have generated a cmp instruction. I don't have any other GCC version installed on the machine, so I cannot test whether GCC 11.4.0 behaves differently.
[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 --- Comment #4 from Andrew Pinski --- Note 10.5.0 was the last release in the GCC 10.x series, can you test out GCC 11.4.0 out?
[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 Andrew Pinski changed: What|Removed |Added See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=108498 --- Comment #3 from Andrew Pinski --- Maybe PR 108498
[Bug target/110772] strange code generated for bit-field access
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772 --- Comment #2 from Andrew Pinski --- I am trying to understand what you think is wrong here? lsrsr3, r3, #7 means logical shift right by 7 and compare against 0. Also this is big-endian arm so the order of bit fields will be different than little-endian. This is extracting one bit from the whole byte. x86 has an instruction (testb) which does the testing that way. arm does not. powerpc does not either. aarch64 has an instruction too. I don't see anything wrong with the code generation here at all. Take: ``` struct t { _Bool a0:1; _Bool a1:1; _Bool a2:1; _Bool a3:1; _Bool a4:1; _Bool a5:1; _Bool a6:1; _Bool a7:1; }; int g(); int h(); int f(struct t *a) { if(a->a0) return g(); return h(); } int f1(struct t *a) { if(a->a7) return g(); return h(); } int f2(_Bool *a) { if(*a) return g(); return h(); } ``` I don't see anything wrong with the above code generation for either arm or x86_64 (or powerpc).