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

Reply via email to