https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111564
Bug ID: 111564 Summary: Missed optimization of Loop Unswitch Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: 652023330028 at smail dot nju.edu.cn Target Milestone: --- Hello, we found some optimizations (regarding Loop Unswitch) that GCC may have missed. We would greatly appreicate if you can take a look and let us know what you think. Here are two examples. Example 1: https://godbolt.org/z/G3xGvGxq1 Given the following code: ```c++ extern int var_21; extern int var_25; extern int var_28; extern int var_29; void test(int var_0, int var_1, int var_2, int var_3, int var_4, int var_5, int var_6, int var_7, int var_8, int var_9, int var_10, int var_11, int var_12, int var_13, int var_14, int var_15, int var_16, int var_17) { for (int i_0 = 0/*0*/; i_0 < ((((((((var_17)) ? (((819565140) + (var_9))) : ((((var_16)) ? (2141366111) : (var_17)))))) ? (((((((var_4)) ? (var_16) : (var_17)))) ? (779921519) : (((var_1) + (var_8))))) : (((((((var_10)) ? (var_12) : (var_5)))) ? ((((var_15)) ? (var_16) : (var_12))) : ((((var_3)) ? (var_0) : (var_11))))))) - (779921500))/*19*/; i_0 += 4/*4*/) { var_21 += var_17; if (var_3) { var_25 += var_17 ? -212529188 : (((var_6) ? (var_5 ? 2029341098 : var_13) : var_11)); var_28 += var_8 ? ((var_10 ? (var_13 - var_1) : var_14 ? var_17 : var_8)) : (var_6 ? 942541005 : var_1 / var_9); var_29 += var_2 ? var_6 : ((var_9 ? var_8 : (var_11 ? var_2 : var_15))); } } } ``` Because `var_3` is a loop invariant so we can hoist the if condition out of the loop, but gcc-trunk -O3 dose not (main parts): ```asm test(int, int, int, int, int): ... .L154: cmp edx, ecx jle .L9 test r10d, r10d je .L153 ... .L153: add ecx, 4 mov eax, 1 jmp .L154 ``` Example 2: https://godbolt.org/z/WcMnz97jv Given the following code: ```c++ extern int var_13; extern int var_15; extern int var_17; extern int var_19; extern int var_20; extern int var_24; void test(int var_0, int var_1, int var_2, int var_3, int var_4, int var_5, int var_6, int var_7, int var_8, int var_9, int var_10) { for (int i_0 = ((var_9) + (1516547146))/*0*/; i_0 < (((-((-((((var_4)) ? (var_6) : (var_8))))))) + (960893662))/*16*/; i_0 += ((var_0) + (1994872666))/*1*/) { if (var_1) { var_13 += (var_0 ? var_8 : var_7) ? (var_0 ? var_7 : var_4) : ((var_7 ? var_1 : var_2) ? 1 : 2); } var_15 += (var_0 ? var_9 : var_6) ? (var_4 ? !var_5 : (var_7 ? var_3 : var_9)) : var_8; var_17 += var_3 ? ((var_4 ? var_5 : var_8) ? var_3 : var_1) : (var_5 ? var_8 : var_0); var_19 += (var_1 ? var_8 : var_2) ? (var_1 ? (var_7 ? var_3 : var_9) : !var_3) : var_9; var_20 += var_10 ? var_3 : (var_4 ? var_10 : var_8); var_24 += var_0 ? -var_5 : (var_8 ? (var_3 ? var_8 : var_1) : (var_6 ? var_6 : var_5)); } } ``` Similarly, `var_1` is an loop invariant and should be hoisted out of the loop as well. But gcc-trunk -O3 does not: ```asm test(int, int, int, int, int): ... .L273: test ecx, ecx je .L87 mov r8d, DWORD PTR [rsp+64] add DWORD PTR [rsp-28], r8d test ebp, ebp jne .L120 add DWORD PTR [rsp-32], ecx test edx, edx jne .L271 .L121: mov BYTE PTR [rsp-14], 1 .L89: mov ebx, DWORD PTR [rsp-12] test r12d, r12d cmovne ebx, ecx .L92: add r9d, ebx test r10d, r10d je .L100 .L102: cmp BYTE PTR [rsp-13], 0 mov ebx, edx jne .L103 .L99: mov ebx, ebp .L103: mov r8d, DWORD PTR [rsp+88] add edi, ebx test r8d, r8d je .L104 .L274: mov ebx, r11d add eax, r13d add esi, edx sub ebx, r12d cmp r15d, eax jle .L272 .L130: mov r11d, ebx test r10d, r10d jne .L273 ... ``` Thank you very much for your time and effort! We look forward to hearing from you.