https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91131
Bug ID: 91131 Summary: Bad bitfield coalescing Product: gcc Version: 8.3.0 URL: http://knaldgas.dk/~pdj/bitfields/ Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: pdj at knaldgas dot dk Target Milestone: --- In both C and Ada, bitfield coalescing does not work right, or at least not optimal. Since the issue manifests itself in the same way in both C and Ada front-ends, and on ARM, AVR and X86_64 back-ends, I presume that that the issue must lie somewhere in between. Please see past that C bitfields are defective by definition; Ada's definition is pretty well-defined. Seen on GCC version 4.9.3, 8.3.0 and reportedly also on 9.1. The key point below is that all assignments have a data-width of less or equal the machines data-width, and can be fully evaluated at compile time. Pseudo-code: type Rec_Type record A: 3 bits B: 1 bit C: 4 bits end (packed, 8-bit wide) volatile Rec_A : Rec_Type volatile Rec_B : Rec_Type volatile Rec_C : Rec_Type Rec_A := (A => 0, B => 1, C => 0) results in one pre-calculated constant byte being assigned directly. This is the way all such assignments should be. Rec_B := (A => 1, B => 1, C => 1) results in one pre-calculated value being stored in a memory location, which is then ĺoaded and assigned to Rec_B. Unnecessary memory consumption. Rec_C := (A => 0, B => 0, C => 0) results in Read, Modify, Write for each field (3 times). Horrible, and may cause defective execution if Reg_C is a peripheral register! Reading a register does not always give the last value written to it. Also Writing bits in "random" order may cause malfunction of the device. In Ada the Reg_C problem can be mitigated by using pragma Atomic instead, this still causes a memory location to be used for the evaluated constant that could just as well be loaded as an immediate. I've uploaded sources, preprocessed file and Makefile/GPR to this location: http://knaldgas.dk/~pdj/bitfields/ - The c-file is just compiled with gcc -O<whatever> -c main.c Pretty odd that three similar assignments can give three different kinds of code generation...