https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115817

            Bug ID: 115817
           Summary: [AVR] Suboptimal code for zeroing SRAM byte from ISR
           Product: gcc
           Version: 14.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dimich.dmb at gmail dot com
  Target Milestone: ---

There are two almost identical ISRs, the difference is only an immediate value
to be stored in SRAM.

```
static volatile unsigned char flag;

 __attribute__ ((__signal__,__used__, __externally_visible__))
void __vector_set_one(void)
{
    flag = 1;
}

__attribute__ ((__signal__,__used__, __externally_visible__))
void __vector_set_zero(void)
{
    flag = 0;
}
```

(The real code is reduced to this MRE to avoid ISR macro from avr-libc header)

First function compiles to the following code:

0000000c <__vector_set_zero>:
   c:   1f 92           push    r1
   e:   1f b6           in      r1, 0x3f        ; 63
  10:   1f 92           push    r1
  12:   11 24           eor     r1, r1
  14:   10 92 00 00     sts     0x0000, r1      ; 0x800000 <__SREG__+0x7fffc1>
  18:   1f 90           pop     r1
  1a:   1f be           out     0x3f, r1        ; 63
  1c:   1f 90           pop     r1
  1e:   18 95           reti

which looks overcomplicated comparing to the first one:

00000000 <__vector_set_one>:
   0:   8f 93           push    r24
   2:   81 e0           ldi     r24, 0x01       ; 1
   4:   80 93 00 00     sts     0x0000, r24     ; 0x800000 <__SREG__+0x7fffc1>
   8:   8f 91           pop     r24
   a:   18 95           reti

For other non-zero values the code is the same as for `__vector_set_one` except
the value itself.

The same difference is observed in final ELF binary, regardless of whether
compiled and linked with or without `-flto`. 

Preprocessed file:
```
# 0 "example.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "example.c"
static volatile unsigned char flag;

 __attribute__ ((__signal__,__used__, __externally_visible__))
void __vector_set_one(void)
{
    flag = 1;
}

__attribute__ ((__signal__,__used__, __externally_visible__))
void __vector_set_zero(void)
{
    flag = 0;
}
```

GCC version and build flags: 
$ avr-gcc -v
Using built-in specs.
Reading specs from /usr/lib/gcc/avr/14.1.0/device-specs/specs-avr2
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/14.1.0/lto-wrapper
Target: avr
Configured with: /build/avr-gcc/src/gcc-14.1.0/configure
--disable-install-libiberty --disable-libssp --disable-libstdcxx-pch
--disable-libunwind-exceptions --disable-linker-build-id --disable-nls
--disable-werror --disable-__cxa_atexit --enable-checking=release
--enable-clocale=gnu --enable-gnu-unique-object --enable-gold
--enable-languages=c,c++ --enable-ld=default --enable-lto --enable-plugin
--enable-shared --infodir=/usr/share/info --libdir=/usr/lib
--libexecdir=/usr/lib --mandir=/usr/share/man --prefix=/usr --target=avr
--with-as=/usr/bin/avr-as --with-gnu-as --with-gnu-ld --with-ld=/usr/bin/avr-ld
--with-plugin-ld=ld.gold --with-system-zlib --with-isl
--enable-gnu-indirect-function
Thread model: single
Supported LTO compression algorithms: zlib zstd
gcc version 14.1.0 (GCC)

System: Arch Linux, x86_64 GNU/Linux

Compilation:
$ avr-gcc -Wall -pedantic -Os -mmcu=attiny13a --save-temps -c -o example.o
example.c

Expected code:
__vector_set_zero:
    push    r24
    ldi     r24, 0x00
    sts     flag, r24
    pop     r24
    reti

Reply via email to