https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116307
--- Comment #3 from Kacper Michajłow <kasper93 at gmail dot com> --- (In reply to Kacper Michajłow from comment #2) > (In reply to Andrew Pinski from comment #1) > > Note I don't think the warning is not incorrect. Nor I don't think unrolling > > by 3 is wrong either. > > Could you explain why unrolling by 3 is not wrong in this case? Technically > it is not wrong, but why unrolling by 2 is not enough? Just to expand. Strictly speaking UB of writing past the end of `a` is invoked after get_val() function call, so unrolling by 3 makes this call happen. I guess it is not always obvious how to prune the "last" iteration. But gcc seems to know it is unnecessary, so maybe the store could be removed after the call. But I'm guessing, without looking into the actual code. The following example is unrolled by 2, because the store is before the call and the one-past iteration is completely removed, compared to previous example. --- struct A { char a[2]; char b[2]; }; int num; int get_val(void); void foo(struct A *a) { for (int p = 0; p < num; p++) { a->a[p] = 0; a->a[p] = get_val(); } } --- foo(A*): mov eax, DWORD PTR num[rip] test eax, eax jle .L4 push rbx mov rbx, rdi mov BYTE PTR [rdi], 0 call get_val() mov BYTE PTR [rbx], al cmp DWORD PTR num[rip], 1 jle .L1 mov BYTE PTR [rbx+1], 0 call get_val() mov BYTE PTR [rbx+1], al .L1: pop rbx ret .L4: ret num: .zero 4