https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109650
Bug ID: 109650 Summary: avr-gcc incorrect code with -Os Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: thierer at web dot de Target Milestone: --- Created attachment 54942 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54942&action=edit preprocessed input file The attached file imho creates invalid code with avr-gcc 12.2.0 when compiling with "-Os". The same code works with either different optimization settings or avr-gcc 11.3.0 (haven't tried any other versions). The misbehaving code is this function: static bool test_func(uint8_t p1, uint8_t p2) { if (p1 == 0 || p1 > 7) return false; if (p1 < 3) return p2 <= 8; else if (p1 < 5) return p2 <= 6; else if (p1 < 7) return p2 <= 4; else return p2 <= 2; } It should return false for all values of p2 if p1 is 0 or > 7 and the result should depend on p2 for inbetween values of p1. The code contains a lot of boilerplate for sending a showcase output over USART0. This is the result for values of 0 <= p2 < 10 (columns) for 0 < p1 < 9 (rows): 0123456789 0 ?????????? 1 XXXXXXXXX? 2 XXXXXXXXX? 3 XXXXXX???? 4 XXXXXX???? 5 XXXX?????? 6 XXXX?????? 7 XX???????? 8 ?????????? "X" means test_func() returned true, "?" false. The result for p1 in [0,1,2,8] is correct, all the other results are off (too low) by 1. For example, for p1 == 3 the function should return true for all p2 <= 6, but it only does for <= 5. I'm not too familiar with AVR assembly, but the problem seems to be that the comparisons that calculate the result value all use the same brlo (branch if lower) instruction at .L34, but the compiler fails to compensate for the "lower" instead of "lower or equal" for all but the first (<= 8) condition: .L21: cpi r17,lo8(7) brsh .L25 cpi r28,lo8(3) brsh .L12 cpi r29,lo8(9) ; this correctly compares to 9 == 8+1 .L34: brlo .L27 .L25: ldi r24,lo8(63) .L11: [...] .L12: cpi r28,lo8(5) brsh .L15 cpi r29,lo8(6) ; but this does not (should be 6+1 == 7) rjmp .L34 .L15: cpi r28,lo8(7) breq .L17 cpi r29,lo8(4) ; neither does this (should be 4+1 == 5) rjmp .L34 .L17: cpi r29,lo8(2) ; nor this (should be 2+1 == 3) rjmp .L34 .L27: Tested with the respective Arch Linux x86_64 avr-gcc packages. Output of "avr-gcc -v": > avr-gcc -v -save-temps -Wall -Wextra -mmcu=atmega1284p -Os > --param=min-pagesize=0 avr-bug.c Using built-in specs. Reading specs from /usr/lib/gcc/avr/12.2.0/device-specs/specs-atmega1284p COLLECT_GCC=avr-gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/12.2.0/lto-wrapper Target: avr Configured with: /build/avr-gcc/src/gcc-12.2.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 12.2.0 (GCC) COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-Os' '--param=min-pagesize=0' '-mdouble=32' '-mlong-double=64' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51' '-dumpdir' 'a-' /usr/lib/gcc/avr/12.2.0/cc1 -E -quiet -v -imultilib avr51 -D__AVR_ATmega1284P__ -D__AVR_DEVICE_NAME__=atmega1284p avr-bug.c -mn-flash=2 -mno-skip-bug -mdouble=32 -mlong-double=64 -mmcu=avr51 -Wall -Wextra -Os -fpch-preprocess -o a-avr-bug.i ignoring nonexistent directory "/usr/lib/gcc/avr/12.2.0/../../../../avr/sys-include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/avr/12.2.0/include /usr/lib/gcc/avr/12.2.0/include-fixed /usr/lib/gcc/avr/12.2.0/../../../../avr/include End of search list. COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-Os' '--param=min-pagesize=0' '-mdouble=32' '-mlong-double=64' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51' '-dumpdir' 'a-' /usr/lib/gcc/avr/12.2.0/cc1 -fpreprocessed a-avr-bug.i -mn-flash=2 -mno-skip-bug -quiet -dumpdir a- -dumpbase avr-bug.c -dumpbase-ext .c -mdouble=32 -mlong-double=64 -mmcu=avr51 -Os -Wall -Wextra -version --param=min-pagesize=0 -o a-avr-bug.s GNU C17 (GCC) version 12.2.0 (avr) compiled by GNU C version 12.1.1 20220730, GMP version 6.2.1, MPFR version 4.1.0-p13, MPC version 1.2.1, isl version isl-0.26-GMP warning: MPFR header version 4.1.0-p13 differs from library version 4.2.0. warning: MPC header version 1.2.1 differs from library version 1.3.1. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 GNU C17 (GCC) version 12.2.0 (avr) compiled by GNU C version 12.1.1 20220730, GMP version 6.2.1, MPFR version 4.1.0-p13, MPC version 1.2.1, isl version isl-0.26-GMP warning: MPFR header version 4.1.0-p13 differs from library version 4.2.0. warning: MPC header version 1.2.1 differs from library version 1.3.1. GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072 Compiler executable checksum: 00c69299beaa7f88846ded0b751d0e18 COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-Os' '--param=min-pagesize=0' '-mdouble=32' '-mlong-double=64' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51' '-dumpdir' 'a-' /usr/bin/avr-as -v -mmcu=avr51 -mgcc-isr -mno-skip-bug -o a-avr-bug.o a-avr-bug.s GNU assembler version 2.40 (avr) using BFD version (GNU Binutils) 2.40 COMPILER_PATH=/usr/lib/gcc/avr/12.2.0/:/usr/lib/gcc/avr/12.2.0/:/usr/lib/gcc/avr/:/usr/lib/gcc/avr/12.2.0/:/usr/lib/gcc/avr/ LIBRARY_PATH=/usr/lib/gcc/avr/12.2.0/avr51/:/usr/lib/gcc/avr/12.2.0/../../../../avr/lib/avr51/:/usr/lib/gcc/avr/12.2.0/:/usr/lib/gcc/avr/12.2.0/../../../../avr/lib/ COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-Os' '--param=min-pagesize=0' '-mdouble=32' '-mlong-double=64' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51' '-dumpdir' 'a.' /usr/lib/gcc/avr/12.2.0/collect2 -plugin /usr/lib/gcc/avr/12.2.0/liblto_plugin.so -plugin-opt=/usr/lib/gcc/avr/12.2.0/lto-wrapper -plugin-opt=-fresolution=a.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lm -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-latmega1284p -mavr51 -Tdata 0x800100 /usr/lib/gcc/avr/12.2.0/../../../../avr/lib/avr51/crtatmega1284p.o -L/usr/lib/gcc/avr/12.2.0/avr51 -L/usr/lib/gcc/avr/12.2.0/../../../../avr/lib/avr51 -L/usr/lib/gcc/avr/12.2.0 -L/usr/lib/gcc/avr/12.2.0/../../../../avr/lib a-avr-bug.o --start-group -lgcc -lm -lc -latmega1284p --end-group COLLECT_GCC_OPTIONS='-v' '-save-temps' '-Wall' '-Wextra' '-Os' '--param=min-pagesize=0' '-mdouble=32' '-mlong-double=64' '-specs=device-specs/specs-atmega1284p' '-mmcu=avr51' '-dumpdir' 'a.'