https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97775
Bug ID: 97775 Summary: Wrong code with bitfield Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: hubicka at gcc dot gnu.org Target Milestone: --- The follwing testcase reduced from ssd/t2.c #include <stdio.h> void dump (void *p, unsigned int len) { const char digits[17] = "0123456789abcdef"; unsigned char *a = (unsigned char *)p; int i; for (i = 0; i < len; i++) { putchar (' '); putchar (digits[a[i] / 16]); putchar (digits[a[i] % 16]); } } void put (const char s[]) { int i; for (i = 0; s[i]; i++) putchar (s[i]); } void new_line (void) { putchar ('\n'); } struct __attribute__((scalar_storage_order("little-endian"), packed)) R1 { unsigned S1 : 2; unsigned I : 32; unsigned S2 : 2; unsigned A1 : 9; unsigned A2 : 9; unsigned A3 : 9; unsigned B : 1; }; struct R1 My_R1 = { 2, 0x12345678, 1, 0xAB, 0xCD, 0xEF, 1 }; int main (void) { struct R1 Local_R1; Local_R1.B = 1; #ifdef BAD new_line (); #endif /* { dg-output "Local_R1 : e2 59 d1 48 b4 aa d9 bb.*\n" } */ Local_R1.S1 = 0; Local_R1.I = 0; Local_R1.S2 = 0; Local_R1.A1 = 0; Local_R1.A2 = 0; Local_R1.A3 = 0; Local_R1.B = !Local_R1.B; put ("Local_R1 :"); dump (&Local_R1, sizeof (struct R1)); new_line (); /* { dg-output "Local_R1 : e5 59 d1 48 b0 a0 c1 03.*\n" } */ new_line (); return 0; } Defining BAD canges output < Local_R1 : 00 00 00 00 00 00 00 00 --- > Local_R1 : 00 00 00 00 00 00 00 80 Difference is already in fre1: -Value numbering store Local_R1.B to _3 +Value numbering store Local_R1.B to 1 .... -RPO tracked 17 values available at 3 locations and 17 lattice elements +RPO tracked 17 values available at 0 locations and 17 lattice elements +Replaced BIT_FIELD_REF <Local_R1, 8, 56> with 0 in all uses of _1 = BIT_FIELD_REF <Local_R1, 8, 56>; +Replaced (signed char) _1 with 0 in all uses of _2 = (signed char) _1; +Replaced _2 >= 0 with 1 in all uses of _3 = _2 >= 0; +Deleted redundant store Local_R1.B = _3; +Removing dead stmt Local_R1.B = _3; +Removing dead stmt _3 = _2 >= 0; +Removing dead stmt _2 = (signed char) _1; +Removing dead stmt _1 = BIT_FIELD_REF <Local_R1, 8, 56>; main () { struct R1 Local_R1; - unsigned char _1; - signed char _2; - _Bool _3; <bb 2> : Local_R1.B = 1; @@ -533,10 +540,6 @@ Local_R1.A1 = 0; Local_R1.A2 = 0; Local_R1.A3 = 0; - _1 = BIT_FIELD_REF <Local_R1, 8, 56>; - _2 = (signed char) _1; - _3 = _2 >= 0; - Local_R1.B = _3; put ("Local_R1 :"); dump (&Local_R1, 8); new_line (); Clearly B should be 0 and not 1.