https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115828
Bug ID: 115828 Summary: Inefficient loop termination (should use compare against 0) Product: gcc Version: 14.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: gjl at gcc dot gnu.org Target Milestone: --- Created attachment 58608 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58608&action=edit C99 test case volatile int v; void loop (void) { for (int i = 36; i >= 0; i -= 2) v = i; } In this C99 code with $ avr-gcc stride.c -S -Os -dp -fdump-rtl-expand-details the loop termination is a comparison against -2, like in i = 36 loop: ... i -= 2 if (i != -2) goto loop; However, on many platforms is it easier to test for the sign-bit of i, like in: i -= 2 if (i >= 0) goto loop; As the loop starts with i=36, i will always be >= after the decrement, or else the loop will terminate. The code is already there at .expand, something like: ;; i_5 = i_8 + -2; (insn 9 8 0 (parallel [ (set (reg/v:HI 43 [ i ]) (plus:HI (reg/v:HI 43 [ i ]) (const_int -2 [0xfffffffffffffffe]))) (clobber (scratch:QI)) ]) "stride.c":13:32 discrim 3 -1 (nil)) ;; if (i_5 != -2) (jump_insn 11 9 0 (parallel [ (set (pc) (if_then_else (ne (reg/v:HI 43 [ i ]) (const_int -2 [0xfffffffffffffffe])) (label_ref 10) (pc))) (clobber (scratch:QI)) ]) "stride.c":13:24 discrim 1 -1 (int_list:REG_BR_PROB 1017229100 (nil))) The backend cannot recover from this. FYI, the backend has no doloop or decrement-and-branch pattern, and the issue is independent of -f[no-]wrapv, and is also there with -O2 and -O3. int is a 16-bit type, but the code is similar with char and long instead of int. COLLECT_GCC=avr-gcc Target: avr Configured with: ../../source/gcc-14/configure --target=avr --disable-nls --enable-languages=c,c++ --with-gnu-as --with-gnu-ld --disable-shared --disable-libssp Thread model: single Supported LTO compression algorithms: zlib gcc version 14.1.1 20240509 (GCC) Same happens with current master (future v15).