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.