public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/110772] New: strange code generated for bit-field access
@ 2023-07-21 23:26 roland.illig at gmx dot de
  2023-07-21 23:27 ` [Bug c/110772] " roland.illig at gmx dot de
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: roland.illig at gmx dot de @ 2023-07-21 23:26 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

            Bug ID: 110772
           Summary: strange code generated for bit-field access
           Product: gcc
           Version: 12.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: roland.illig at gmx dot de
  Target Milestone: ---
            Target: arm

Created attachment 55598
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55598&action=edit
precompiled code that generates unrelated diagnostics

In NetBSD's lint, I changed 'struct type_qualifier' from an enum to a set of
bit-fields. It worked well on x86_64 but not on arm and powerpc.

https://github.com/NetBSD/src/commit/35c652085d26b93b94f55312f715361ee0cd2043

On these two 32-bit platforms, lint generated some unrelated and wrong
diagnostics.

I tracked the difference down to a single line of code, and changing that line
changes unrelated code.

In the attached p5.i, applying the following diff changes not only the code in
cgram.y:529, but also in cgram.y:489.

$ diff -u p5.i p3.i
--- p5.i        2023-07-22 00:22:30.748103516 +0200
+++ p3.i        2023-07-22 00:22:05.448298739 +0200
@@ -6424,7 +6424,7 @@
 case 68:
 # 528 "cgram.y"
  {
-  if (!yystack.l_mark[0].y_type_qualifiers.tq_const)
+  if (!yystack.l_mark[0].y_seen_statement)
    yyerror("Bad attribute");
  }
 # 1 ""


$ gcc --version
gcc (nb2 20230710) 10.5.0

$ uname -mp
evbarm earmv7hfeb

$ gcc -O2 -S p5.i -fverbose-asm
$ gcc -O2 -S p3.i -fverbose-asm
$ gcc -O2 -c p5.i
$ gcc -O2 -c p3.i
$ objdump -dr p5.o > p5.dis
$ objdump -dr p3.o > p3.dis

$ diff -u p5.dis p3.dis
...
-     ba8:      e1b033a3        lsrs    r3, r3, #7
+     ba8:      e3530000        cmp     r3, #0
...
-    1010:      e1b033a3        lsrs    r3, r3, #7
+    1010:      e3530000        cmp     r3, #0

The code has changed in two places. Searching for the text "#7" in the p5.s
file shows that the two places where the code has changed are in cgram.y:529
and cgram.y:489.

I doubt that the code invokes undefined behavior, as it is fairly standard yacc
code. Therefore I suspect a compiler error.

Compiling the code with -Os or -O1 instead of -O2 does not show this behavior.

Removing the ':1' from the members in struct type_qualifier does not show this
behavior.

Compiling the code on x86_64 or i386 does not show this behavior.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
@ 2023-07-21 23:27 ` roland.illig at gmx dot de
  2023-07-21 23:53 ` [Bug target/110772] " pinskia at gcc dot gnu.org
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: roland.illig at gmx dot de @ 2023-07-21 23:27 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

--- Comment #1 from Roland Illig <roland.illig at gmx dot de> ---
Created attachment 55599
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55599&action=edit
precompiled code that works as intended

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
  2023-07-21 23:27 ` [Bug c/110772] " roland.illig at gmx dot de
@ 2023-07-21 23:53 ` pinskia at gcc dot gnu.org
  2023-07-22  0:08 ` pinskia at gcc dot gnu.org
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-07-21 23:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I am trying to understand what you think is wrong here?

lsrs    r3, 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).

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
  2023-07-21 23:27 ` [Bug c/110772] " roland.illig at gmx dot de
  2023-07-21 23:53 ` [Bug target/110772] " pinskia at gcc dot gnu.org
@ 2023-07-22  0:08 ` pinskia at gcc dot gnu.org
  2023-07-22  0:11 ` pinskia at gcc dot gnu.org
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-07-22  0:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=108498

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Maybe PR 108498  ....

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
                   ` (2 preceding siblings ...)
  2023-07-22  0:08 ` pinskia at gcc dot gnu.org
@ 2023-07-22  0:11 ` pinskia at gcc dot gnu.org
  2023-07-22 15:21 ` roland.illig at gmx dot de
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-07-22  0:11 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Note 10.5.0 was the last release in the GCC 10.x series, can you test out GCC
11.4.0 out?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
                   ` (3 preceding siblings ...)
  2023-07-22  0:11 ` pinskia at gcc dot gnu.org
@ 2023-07-22 15:21 ` roland.illig at gmx dot de
  2023-07-22 15:23 ` roland.illig at gmx dot de
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: roland.illig at gmx dot de @ 2023-07-22 15:21 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

--- Comment #5 from Roland Illig <roland.illig at gmx dot de> ---
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]
>         ldrb    r3, [r4, #-8]   @ $1.y_seen_statement
>         cmp     r3, #0
>         beq     .L368
> @ cgram.y:550:          $$ = build_unary($2 == INC ? INCAFT : DECAFT, $3, $1);
>         ldrb    r3, [r4]
> @ cgram.y:1802:
>         lsrs    r3, 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.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
                   ` (4 preceding siblings ...)
  2023-07-22 15:21 ` roland.illig at gmx dot de
@ 2023-07-22 15:23 ` roland.illig at gmx dot de
  2023-07-22 15:29 ` roland.illig at gmx dot de
  2023-07-22 15:50 ` roland.illig at gmx dot de
  7 siblings, 0 replies; 9+ messages in thread
From: roland.illig at gmx dot de @ 2023-07-22 15:23 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

Roland Illig <roland.illig at gmx dot de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #55598|0                           |1
        is obsolete|                            |
  Attachment #55599|0                           |1
        is obsolete|                            |

--- Comment #6 from Roland Illig <roland.illig at gmx dot de> ---
Created attachment 55611
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55611&action=edit
Precompiled source from comment 5

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
                   ` (5 preceding siblings ...)
  2023-07-22 15:23 ` roland.illig at gmx dot de
@ 2023-07-22 15:29 ` roland.illig at gmx dot de
  2023-07-22 15:50 ` roland.illig at gmx dot de
  7 siblings, 0 replies; 9+ messages in thread
From: roland.illig at gmx dot de @ 2023-07-22 15:29 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

--- Comment #7 from Roland Illig <roland.illig at gmx dot de> ---
Created attachment 55612
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55612&action=edit
Preprocessed source from comment 5

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug target/110772] strange code generated for bit-field access
  2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
                   ` (6 preceding siblings ...)
  2023-07-22 15:29 ` roland.illig at gmx dot de
@ 2023-07-22 15:50 ` roland.illig at gmx dot de
  7 siblings, 0 replies; 9+ messages in thread
From: roland.illig at gmx dot de @ 2023-07-22 15:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110772

--- Comment #8 from Roland Illig <roland.illig at gmx dot de> ---
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.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-07-22 15:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-07-21 23:26 [Bug c/110772] New: strange code generated for bit-field access roland.illig at gmx dot de
2023-07-21 23:27 ` [Bug c/110772] " roland.illig at gmx dot de
2023-07-21 23:53 ` [Bug target/110772] " pinskia at gcc dot gnu.org
2023-07-22  0:08 ` pinskia at gcc dot gnu.org
2023-07-22  0:11 ` pinskia at gcc dot gnu.org
2023-07-22 15:21 ` roland.illig at gmx dot de
2023-07-22 15:23 ` roland.illig at gmx dot de
2023-07-22 15:29 ` roland.illig at gmx dot de
2023-07-22 15:50 ` roland.illig at gmx dot de

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).