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).

Reply via email to