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

--- Comment #2 from Yi <652023330028 at smail dot nju.edu.cn> ---
(In reply to Andrew Pinski from comment #1)
> _5 = var_0_16(D) + var_6_18(D);
>   invariant up to level 1, cost 1.
> 
> Basically because the cost is not high enough ...
> 
> If you use   --param=lim-expensive=1. then it will pull it out of the loop.
> 
> So the cost model is doing the correct thing here ...


Thank you very much for your prompt reply! It took me some time to confirm our
work. For Example 1, GCC does exactly what you say it does. But for Example 2,
it doesn't seem to work as expected.

https://godbolt.org/z/eeWThnqWs

Given the following code: 
```c++
extern int var_24;
void test(int var_2, int var_3, int var_8, int var_10, int var_14) {

    for (int i_2 = -3247424; i_2 < 19; i_2 += var_3 + 1056714155) 
    {
        if(var_3){
            var_24 += (-(200 / var_10)) + (-var_8);
            var_24 += var_14 + var_2;
        }

        i_2+=i_2/3;
    }
}
```

We note that `(-(200 / var_10)) + (-var_8) + var_14 + var_2` as a whole can be
treated as a loop invariant, but gcc-trunk -O3 --param=lim-expensive=1 does
not:

```asm
test(int, int, int, int, int):
        mov     r10d, edx
        test    esi, esi
        je      .L1
        mov     eax, -200
        mov     edx, -1
        mov     r9d, DWORD PTR var_24[rip]
        add     r8d, edi
        idiv    ecx
        lea     edi, [rsi+1056714155]
        mov     ecx, -3247424
        sub     eax, r10d
.L3:
        movsx   rdx, ecx
        mov     esi, ecx
        add     r9d, eax                # ... + (-(200 / var_10)) + (-var_8)
        imul    rdx, rdx, 1431655766
        sar     esi, 31
        add     r9d, r8d                # ... + var_14 + var_2
        shr     rdx, 32
        sub     edx, esi
        add     ecx, edx
        add     ecx, edi
        cmp     ecx, 18
        jle     .L3
        mov     DWORD PTR var_24[rip], r9d
.L1:
        ret
```

Reply via email to