Skip to content

Missed optimization of loopDeletion probably because of a missing loopUnswitch #70597

@ZY546

Description

@ZY546

https://godbolt.org/z/TW9b71zPM

int b, c;
int n;
void test() {
  for (int i = 0; i < 1000; i += b) {
    if(c < 0){
        c = n;
    }
  }
}

In the test code, the value of c only gets a chance to change when it first enters the loop, so from there we can make the following optimizations:

If initially c<0 holds, then the loop is not executed.

Otherwise, c is a loop invariant for all subsequent iterations of the loop, which can be optimized using loopUnswitch.

Furthermore, if we optimize via loopUnswitch, we see that the entire loop is unnecessary.

Finally, we get the expected code:

test():                               # @test()
        cmp     dword ptr [rip + c], 0
        js      .LBB0_1
        ret
.LBB0_1:                                # %if.then
        mov     eax, dword ptr [rip + n]
        mov     dword ptr [rip + c], eax
        ret

But Clang:

test():                               # @test()
        mov     eax, dword ptr [rip + b]
        mov     esi, dword ptr [rip + c]
        xor     ecx, ecx
        mov     edx, dword ptr [rip + n]
        jmp     .LBB0_1
.LBB0_3:                                # %for.inc
        add     ecx, eax
        cmp     ecx, 1000
        jge     .LBB0_4
.LBB0_1:                                # %for.body
        test    esi, esi
        jns     .LBB0_3
        mov     dword ptr [rip + c], edx
        mov     esi, edx
        jmp     .LBB0_3
.LBB0_4:                                # %for.cond.cleanup
        ret

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions