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: ul...@t-online.de 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