[Bug target/110772] strange code generated for bit-field access

2023-07-22 Thread roland.illig at gmx dot de via Gcc-bugs
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

2023-07-22 Thread roland.illig at gmx dot de via Gcc-bugs
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

2023-07-22 Thread roland.illig at gmx dot de via Gcc-bugs
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

2023-07-22 Thread roland.illig at gmx dot de via Gcc-bugs
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

2023-07-21 Thread pinskia at gcc dot gnu.org via Gcc-bugs
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

2023-07-21 Thread pinskia at gcc dot gnu.org via Gcc-bugs
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

2023-07-21 Thread pinskia at gcc dot gnu.org via Gcc-bugs
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).