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 ```