Re: AVR/GNU C Compiler 15 - Non efficient bit access

Henrik Holst via Gcc-help <[email protected]> Fri, 13 Feb 2026 16:10:25 +0100
Newsgroups gmane.comp.gcc.help
Message-ID <CAGwK9dymNCuXRGVEyOE1sGPDOTy=HTLH695d=Rb01-eNUQO0dw@mail.gmail.com>
ignore me, I missed the 5.0 generation...

Den fre 13 feb. 2026 kl 16:09 skrev Henrik Holst <
[email protected]>:

> sorry since I am not 100% familiar with the AVR architecture but isn't the
> generated code from GCC 15.2 1 cycle (2 vs 3) less than what 15.1 generates
> and thus actually more efficient?
>
> /HH
>
> Den fre 13 feb. 2026 kl 15:47 skrev <[email protected]>:
>
>> I'm working on an embedded project using an AVR microcontroller.
>>
>> I've noticed that version 15 generates non-efficient access to registers
>> that have single instruction opcodes available.
>>
>>
>>
>> The AVR Instruction Set provides opcodes for I/O direct addressing:
>> SBIC: Skip if Bit in I/O Register Cleared
>>
>> SBIS: Skip if Bit in I/O Register Set
>>
>>
>>
>> This is a minimal example that generates the problem:
>>
>>
>>
>>
>> typedef __UINT8_TYPE__ uint8_t;
>>
>> #define SFR (*(volatile uint8_t*) (1 + __AVR_SFR_OFFSET__))
>>
>> char File1 (char angle, char scale);
>>
>> void File2 (void)
>>
>> {
>>
>>     if (!(SFR & (1 << 4)))
>>
>>         for (uint8_t i = 0; i < 3; ++i)
>>
>>             File1 (i, 1);
>>
>> }
>>
>>
>>
>> Compile with:
>> $ avr-gcc -mmcu=atmega8 -S -Os -dp x.c
>>
>>
>>
>> A work-around was suggested by SprinterSB at the avrfreaks forum:
>>
>>
>>
>> static inline __attribute__((__always_inline__))
>>
>> uint8_t bit_is_clear (uint8_t val, uint8_t bitno)
>>
>> {
>>
>>     return ! (val & (1u << bitno));
>>
>> }
>>
>> static inline __attribute__((__always_inline__))
>>
>> uint8_t bit_is_set (uint8_t val, uint8_t bitno)
>>
>> {
>>
>>     return !! (val & (1u << bitno));
>>
>> }
>>
>>
>>
>> This worked on some instances around my project, however, I tried in the
>> example below and it didn't solve the non-efficient access:
>>
>>
>>
>> typedef __UINT8_TYPE__ uint8_t;
>>
>> #define SFR1 (*(volatile uint8_t*) (0x01 + __AVR_SFR_OFFSET__))
>>
>> #define SFRC (*(volatile uint8_t*) (0x0C + __AVR_SFR_OFFSET__))
>>
>> void Func1(char a, char *p);
>>
>> static inline __attribute__((__always_inline__))
>>
>> uint8_t my_bit_is_clear (uint8_t val, uint8_t bitno) {
>>
>>     return ! (val & (1u << bitno));
>>
>> }
>>
>> static inline __attribute__((__always_inline__))
>>
>> uint8_t my_bit_is_set (uint8_t val, uint8_t bitno) {
>>
>>     return !! (val & (1u << bitno));
>>
>> }
>>
>> static void Func3(void);
>>
>> void Func2(void) {
>>
>>     do {
>>
>>         Func1(0,0);
>>
>>         if(my_bit_is_set(SFRC, 1)) Func1(0,0);
>>
>>         else Func3();
>>
>>         if(my_bit_is_set(SFRC,0)) {
>>
>>             SFRC = 1;
>>
>>         }
>>
>>     } while(my_bit_is_clear(SFRC, 2));
>>
>> }
>>
>> void Func3(void) {
>>
>>     if(my_bit_is_set(SFRC, 3)) {
>>
>>         Func1(0,0);
>>
>>         uint8_t Ones=SFR1, Tens=0;
>>
>>         while (Ones>=10) { Tens++; Ones-=10; }
>>
>>         Func1(5,(uint8_t *)Tens);
>>
>>         Func1(5,(uint8_t *)Ones);
>>
>>     } else {
>>
>>         Func1(9,(uint8_t *)(100+SFRC));
>>
>>         SFRC = 118;
>>
>>         uint8_t Ones=SFR1, Tens=0;
>>
>>         while (Ones>=10) { Tens++; Ones-=10; }
>>
>>         Func1(9,(uint8_t *)Tens);
>>
>>         Func1(9,(uint8_t *)Ones);
>>
>>      }
>>
>> }
>>
>>
>>
>>
>> AVR/GNU C Compiler 5.4.0 generates the proper code access:
>>
>>
>>
>> SBIS 0x0C,1     Skip if bit in I/O register set
>>
>> RJMP PC+0x0005  Relative jump
>>
>>
>>
>> AVR/GNU C Compiler 15.1.0 generates:
>>
>>
>>
>> IN R24,0x0C     In from I/O location
>>
>> BST R24,1       Bit store from register to T
>>
>> CLR R15          Clear Register
>>
>> BLD R15,1       Bit load from T to register
>>
>> SBRS R24,1      Skip if bit in register set
>>
>>
>>
>> AVR/GNU C Compiler 15.2.0 generates:
>>
>>
>>
>> IN R24,0x0C     In from I/O location
>>
>> MOV R17,R24     Copy register
>>
>> ANDI R17,0x02   Logical AND with immediate
>>
>> SBRS R24,1      Skip if bit in register set
>>
>>
>>
>> Thank you for this great compiler and for making a positive impact on the
>> world!
>>
>> Regards,
>>
>> Gabriel Anzziani
>>
>>