https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109236
Bug ID: 109236 Summary: [avr] Invalid code of signed 16-bit compare optimization Product: gcc Version: 12.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: gandalf at winds dot org Target Milestone: --- I'm seeing incorrect code when -O1 or higher is used on AVR (atmega1284p). The compiler generates code that compares "x" to "y", instead of performing the subtraction and comparing against 0. This subtraction matters since "x" and "y" are signed 16-bit variables, and the math in the expression "x-y <= 0" stays as 16-bit in AVR (as opposed to being promoted to 32-bit ints in e.g. x86). gcc -v: Using built-in specs. Reading specs from /usr/local/avr/lib/gcc/avr/12.2.0/device-specs/specs-avr2 COLLECT_GCC=avr-gcc COLLECT_LTO_WRAPPER=/usr/local/avr/libexec/gcc/avr/12.2.0/lto-wrapper Target: avr Configured with: ../configure --target=avr --prefix=/usr/local/avr --disable-nls --enable-languages=c --disable-bootstrap --disable-libssp Thread model: single Supported LTO compression algorithms: zlib zstd gcc version 12.2.0 (GCC) Sample code: _Bool compare(short x, short y) { return (x-y <= 0); } Compiled using: gcc -O1 -mmcu=atmega1284p -c -o test.o test.c ASM result: 00000000 <compare>: 0: 9c 01 movw r18, r24 2: 81 e0 ldi r24, 0x01 ; 1 4: 62 17 cp r22, r18 <---- X compared directly to Y; no subtraction 6: 73 07 cpc r23, r19 8: 04 f4 brge .+0 ; 0xa <compare+0xa> a: 80 e0 ldi r24, 0x00 ; 0 0000000c <.L2>: c: 08 95 ret I instead expect to see a subtraction between r22:23 and r18:19, then a compare against r1 (zero). The following testcase causes an incorrect computation: compare(-30737, 24799) returns 1 on AVR; expected 0. (-30737 - (24799)) as signed 16-bit = 10000, which is not <= 0. For the record, changing the function to "return ((short)(x-y) <= 0)" produces the same incorrect code. Compiling the function without optimization correctly returns 0. It's possible other signed variable sizes besides 16-bit have the same problem, but I did not test this.