https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118925
Bug ID: 118925
Summary: Comparison of the copy of a volatile register variable
instead of the (register) variable
Product: gcc
Version: 14.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: [email protected]
Target Milestone: ---
Created attachment 60522
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=60522&action=edit
example
There is a circular buffer with 2 indices. The indices are modified in a ISR.
The circular buffer is empty if the both indices are equal.
uint8_t RxBuf[16];
volatile uint8_t RxHead;
volatile uint8_t RxTail;
...
while( RxHead == RxTail ); // wait until new char is in buffer (by ISR)
Works as expected as long as at least one index is not bound to a register <
r8.
For example:
register volatile uint8_t RxHead asm ("r6");
register volatile uint8_t RxHead asm ("r7");
In this case:
while( RxHead == RxTail );
is compiled to the following code:
00000000 <main>:
0: 96 2d mov r25, r6
2: 87 2d mov r24, r7
00000004 <.L2>:
4: 98 17 cp r25, r24
6: f1 f3 breq .-4 ; 0x4 <.L2>
The volatile register variable is copied to a temporary register (r25 or r24)
and only the temporary register is compared. If the ISR changes the indices (r6
or r7), this is not recognized.
This only applies to registers < r8. The same compiled with r8, r9 results:
00000000 <main>:
0: 89 14 cp r8, r9
2: f1 f3 breq .-4 ; 0x0 <main>
GCC version and build flags:
$ avr-gcc -v
Using built-in specs.
Reading specs from /usr/local/avr/lib/gcc/avr/14.2.0/device-specs/specs-avr2
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/usr/local/avr/libexec/gcc/avr/14.2.0/lto-wrapper
Target: avr
Configured with: ../configure --prefix=/usr/local/avr --target=avr
--enable-languages=c,c++ --disable-nls --disable-libssp --with-dwarf2
Thread model: single
Supported LTO compression algorithms: zlib
gcc version 14.2.0 (GCC)
Compilation:
avr-gcc -Os -fwhole-program -mrelax -Wall -Wextra --save-temps -mmcu=avr25
-DF_CPU=1000000 main.c -o main.elf