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

--- Comment #11 from Georg-Johann Lay <gjl at gcc dot gnu.org> ---
Created attachment 55132
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55132&action=edit
C++ test case for v5.4 -Os

I can confirm this with avr-g++-5.4.0 and the attached test case:

> avr-gcc-5.4.0 -xc++ loop.c -Os -S -dp -da -fdump-tree-all

volatile unsigned char x; 

void callee (unsigned char);

void f128 (void)
{
    while (1)
        for (unsigned char i = 0; i < 128; i++)
            x = i;
}

void f128_call (void)
{
    while (1)
        for (unsigned char i = 0; i < 128; i++)
            callee (i);
}

The generated assembly is:

_Z4f128v:
        sts x,__zero_reg__       ;  5   movqi_insn/3    [length = 2]

_Z9f128_callv:
        ldi r24,0        ;  5   movqi_insn/1    [length = 1]
        rcall _Z6calleeh         ;  6   call_insn/2     [length = 1]

This is all of the code because in dump loop.c.073t.cunrolli there is:

void f128() ()
{
  unsigned char i;
  <bb 2>:
  <bb 3>:
  <bb 4>:
  x ={v} 0;
  i_7 = 1;
  __builtin_unreachable ();
}

and similar for the other function.

Reason appears to be that the C++ front-end expand the loop variable as signed
char, and later passes think that there is some signed overflow und Undefined
Behaviour.

With -fwrapv, correct code is generated.

Also, the C front end also uses signed char, but for some reason the C version
works.

A work-around is to use -fwrapv so that signed overflow wraps around.

This is not a target issue, it's some tree optimization where GCC falls in its
own pit as it tries to exploit signed overflow.

I could not reproduce this with later version of the compiler. The next version
I tried was v8.5 (I don't have other versions handy).

I leave this bug open for now.  Maybe the tree folks can pin down which PR this
actually is, and when it was fixed.

Reply via email to